EVG Labs EVG Labs - 3 months ago 22
C# Question

C# Wrapping a 2D array to a Sphere

I'm writing a procedural planet generator and I have the terrain working to a 2D array. The last thing I need to do is be able to "wrap" or convert the array to a globe projection.

It only needs to be in 2D, so it can ignore one hemisphere. Currently the array is a 2:1 aspect.

512x256 Generated Terrain Array

Desired output

Thanks.

Answer

The key idea here is to map x axis of the image on sphere longitudes and the y axis of the image will be mapped on sphere latitudes.

Below is the code from CodeProject, thanks to andalmeida :

Here goes coordinate mapping :

public static double MapCoordinate(double i1, double i2, double w1,
    double w2, double p)
{
    return ((p - i1) / (i2 - i1)) * (w2 - w1) + w1;
}

Load the image :

System.Drawing.Image image1 = new Bitmap(Server.MapPath(
    "./images/worldmap4.gif"));
Bitmap imgBitmap = new Bitmap(image1);

Rotation functions :

public static void RotX(double angle, ref double y, ref double z)
     {
     double y1 = y * System.Math.Cos(angle) - z * System.Math.Sin(angle);
     double z1 = y * System.Math.Sin(angle) + z * System.Math.Cos(angle);
     y = y1;
     z = z1;
     }
public static void RotY(double angle, ref double x, ref double z)
     {
     double x1 = x * System.Math.Cos(angle) - z * System.Math.Sin(angle);
     double z1 = x * System.Math.Sin(angle) + z * System.Math.Cos(angle);
     x = x1;
     z = z1;
     }
public static void RotZ(double angle, ref double x, ref double y)
     {
     double x1 = x * System.Math.Cos(angle) - y * System.Math.Sin(angle);
     double y1 = x * System.Math.Sin(angle) + y * System.Math.Cos(angle);
     x = x1;
     y = y1;
     }

while looping through the 2 dimensions of the image, map phi and theta angles from image coordinates, get the cartesian 3D coordinates from phi and theta, provide some rotation to the obtained 3D points and plot them with respective image color:

for (int i = 0; i < imgBitmap.Width; i++)
     {
     for (int j = 0; j < imgBitmap.Height; j++)
          {
          // map the angles from image coordinates
          double theta = Algebra.MapCoordinate(0.0, imgBitmap.Width - 1,
              theta1, theta0, i);
          double phi = Algebra.MapCoordinate( 0.0, imgBitmap.Height - 1,phi0,
              phi1, j);
          // find the cartesian coordinates
          double x = radius * Math.Sin(phi) * Math.Cos(theta);
          double y = radius * Math.Sin(phi) * Math.Sin(theta);
          double z = radius * Math.Cos(phi);
          // apply rotation around X and Y axis to reposition the sphere
          RotX(1.5, ref y, ref z);
          RotY(-2.5, ref x, ref z);
          // plot only positive points
          if (z > 0)
               {
               Color color = imgBitmap.GetPixel(i, j);
               Brush brs = new SolidBrush(color);
               int ix = (int)x + 100;
               int iy = (int)y + 100;
               graphics.FillRectangle(brs, ix, iy, 1, 1);
               brs.Dispose();
              }
          }
     }
Comments