C# 将二维数组包装到球体
C# Wrapping a 2D array to a Sphere
我正在编写一个程序行星生成器,并且我有一个二维数组的地形。我需要做的最后一件事是能够 "wrap" 或将数组转换为地球投影。
只要是二维的就可以,可以忽略一个半球。当前数组是 2:1 方面。
512x256 Generated Terrain Array
谢谢。
这里的关键思想是将图像的 x 轴映射到球体经度上,图像的 y 轴将映射到球体纬度上。
以下是 CodeProject 的代码,感谢 andalmeida :
这是坐标映射:
public static double MapCoordinate(double i1, double i2, double w1,
double w2, double p)
{
return ((p - i1) / (i2 - i1)) * (w2 - w1) + w1;
}
加载图像:
System.Drawing.Image image1 = new Bitmap(Server.MapPath(
"./images/worldmap4.gif"));
Bitmap imgBitmap = new Bitmap(image1);
旋转函数:
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;
}
在遍历图像的 2 维时,从图像坐标映射 phi 和 theta 角,从 phi 和 theta 获取笛卡尔 3D 坐标,为获得的 3D 点提供一些旋转,并用相应的图像颜色绘制它们:
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();
}
}
}
我正在编写一个程序行星生成器,并且我有一个二维数组的地形。我需要做的最后一件事是能够 "wrap" 或将数组转换为地球投影。
只要是二维的就可以,可以忽略一个半球。当前数组是 2:1 方面。
512x256 Generated Terrain Array
谢谢。
这里的关键思想是将图像的 x 轴映射到球体经度上,图像的 y 轴将映射到球体纬度上。
以下是 CodeProject 的代码,感谢 andalmeida :
这是坐标映射:
public static double MapCoordinate(double i1, double i2, double w1,
double w2, double p)
{
return ((p - i1) / (i2 - i1)) * (w2 - w1) + w1;
}
加载图像:
System.Drawing.Image image1 = new Bitmap(Server.MapPath(
"./images/worldmap4.gif"));
Bitmap imgBitmap = new Bitmap(image1);
旋转函数:
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;
}
在遍历图像的 2 维时,从图像坐标映射 phi 和 theta 角,从 phi 和 theta 获取笛卡尔 3D 坐标,为获得的 3D 点提供一些旋转,并用相应的图像颜色绘制它们:
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();
}
}
}