// Compute Sun geocentric cartesian position given actual position on the globe, // heading, elevation and sun distance public static Vector3d GetGeocentricPosition(Vector3 position, Angle heading, Angle elevation, double sunDistance) { // Untransformed sun pos from globe center Vector3 sun = SMath.SphericalToCartesian(elevation.Degrees, SMath.RadiansToDegrees(Math.PI - heading.Radians), sunDistance); // Now transform it to current location Vector3 pos = SMath.CartesianToSpherical(position.X, position.Y, position.Z); Matrix sunTrans = Matrix.Identity; sunTrans *= Matrix.Translation(0, 0, pos.X); // radius pos sunTrans *= Matrix.RotationY((float)Math.PI / 2 - pos.Y); // lat pos sunTrans *= Matrix.RotationZ(pos.Z); // lon pos sun.TransformCoordinate(sunTrans); return(new Vector3d(-sun.X, -sun.Y, -sun.Z)); }
/// <summary> /// Intermediate points on a great circle /// In previous sections we have found intermediate points on a great circle given either /// the crossing latitude or longitude. Here we find points (lat,lon) a given fraction of the /// distance (d) between them. Suppose the starting point is (lat1,lon1) and the final point /// (lat2,lon2) and we want the point a fraction f along the great circle route. f=0 is /// point 1. f=1 is point 2. The two points cannot be antipodal ( i.e. lat1+lat2=0 and /// abs(lon1-lon2)=pi) because then the route is undefined. /// </summary> /// <param name="f">Fraction of the distance for intermediate point (0..1)</param> public Vector3 IntermediateGCPoint(float f, Angle lat1, Angle lon1, Angle lat2, Angle lon2, Angle d) { double sind = Math.Sin(d.Radians); double cosLat1 = Math.Cos(lat1.Radians); double cosLat2 = Math.Cos(lat2.Radians); double A = Math.Sin((1 - f) * d.Radians) / sind; double B = Math.Sin(f * d.Radians) / sind; double x = A * cosLat1 * Math.Cos(lon1.Radians) + B * cosLat2 * Math.Cos(lon2.Radians); double y = A * cosLat1 * Math.Sin(lon1.Radians) + B * cosLat2 * Math.Sin(lon2.Radians); double z = A * Math.Sin(lat1.Radians) + B * Math.Sin(lat2.Radians); Angle lat = Angle.FromRadians(Math.Atan2(z, Math.Sqrt(x * x + y * y))); Angle lon = Angle.FromRadians(Math.Atan2(y, x)); Vector3 v = SMath.SphericalToCartesian(lat.Degrees, lon.Degrees, World.EquatorialRadius); return(v); }
public static Vector3d GetGeocentricPosition(System.DateTime utcDateTime) { if (World.Settings.SunSynchedWithTime) { // Sun synched with time and date double JD = getJulianDay(utcDateTime); double T = (JD - 2451545.0) / 36525; // number of Julian centuries since Jan 1, 2000, 12 UT double k = Math.PI / 180.0; double M = 357.52910 + 35999.05030 * T - 0.0001559 * T * T - 0.00000048 * T * T * T; // mean anomaly, degree double L0 = 280.46645 + 36000.76983 * T + 0.0003032 * T * T; // mean longitude, degree double DL = (1.914600 - 0.004817 * T - 0.000014 * T * T) * Math.Sin(k * M) + (0.019993 - 0.000101 * T) * Math.Sin(k * 2 * M) + 0.000290 * Math.Sin(k * 3 * M); double L = L0 + DL; // true longitude, degree L = L % 360; // obliquity eps of ecliptic: double eps = 23.0 + 26.0 / 60.0 + 21.448 / 3600.0 - (46.8150 * T + 0.00059 * T * T - 0.001813 * T * T * T) / 3600; double X = Math.Cos(k * L); double Y = Math.Cos(k * eps) * Math.Sin(k * L); double Z = Math.Sin(k * eps) * Math.Sin(k * L); double R = Math.Sqrt(1.0 - Z * Z); double dec = (180 / Math.PI) * Math.Atan(Z / R); // in degrees double RA = (24 / Math.PI) * Math.Atan(Y / (X + R)); // in hours double theta0 = 280.46061837 + 360.98564736629 * (JD - 2451545.0) + 0.000387933 * T * T - T * T * T / 38710000.0; // Greenwich Sidereal Time theta0 = theta0 % 360; RA *= 15; // convert from hours to degrees double tau = theta0 - RA; Vector3d pos = SMath.SphericalToCartesianV3D( -dec, -(tau - 180), 1); return(pos); } else { // Fixed sun heading and elevation double worldRadius = 6378137; // Earth meter Vector3 position = SMath.SphericalToCartesian(DrawArgs.Instance.WorldCamera.Latitude.Degrees, DrawArgs.Instance.WorldCamera.Longitude.Degrees, worldRadius); return(GetGeocentricPosition(position, Angle.FromRadians(World.Settings.SunHeading), Angle.FromRadians(World.Settings.SunElevation), World.Settings.SunDistance)); } }
private void InitWorld() { Vector3 v = SMath.SphericalToCartesian(startlatitude, startlongitude, World.EarthRadius); v.Z = (float)startAltitude * 1.0f; Quaternion4d q = Quaternion4d.EulerToQuaternion(SMath.DegreesToRadians(startlongitude), SMath.DegreesToRadians(startlatitude), 0); Quaternion qz = Quaternion.RotationAxis(new Vector3(0, 0, 1), (float)SMath.DegreesToRadians(startlatitude)); //q.W = qz.W; //q.X = qz.X; //q.Y = qz.Y; //q.Z = qz.Z; //TerrainTileService terrainTileService = new TerrainTileService("http://worldwind25.arc.nasa.gov/tile/tile.aspx", "100", 20, 150, "bil", 8, Path.Combine(EarthSetting.CachePath, "Earth\\TerrainAccessor\\SRTM")); TerrainTileService terrainTileService = new TerrainTileService("http://worldwind25.arc.nasa.gov/tile/tile.aspx", "100", 1, 150, "bil", 6, @"D:\空间数据\重庆H48\bil29107"); TerrainAccessor terrainAccessor = new NltTerrainAccessor("Earth", -180, -90, 180, 90, terrainTileService, null); World _world = new World("Earth", new Vector3d(0, 0, 0), q, this.worldViewer1, terrainAccessor); this.worldViewer1.CurrentWorld = _world; this.worldViewer1.ResetSize(); }
public void Initialize(Device device) { this.numvertices = (this.slice + 1) * (this.stack + 1); this.numtriangles = this.slice * this.stack * 2; this.numindices = this.numtriangles * 3; DoubleTextureVertex[] verts = new DoubleTextureVertex[this.numvertices]; int[] ind = new int[this.numindices]; double stacksize = 180.0 / stack; double slicesize = 360.0 / slice; int index = 0; for (int i = 0; i <= stack; i++) { double lat = -90.0 + i * stacksize; float tv = (float)(i * 1.0 / stack); for (int j = 0; j <= slice; j++) { double lon = -180.0 + j * slicesize; Vector3 v = SMath.SphericalToCartesian(lat, lon, this.radius); Vector3 n = Vector3.Normalize(v); verts[index++] = new DoubleTextureVertex( v, n, (float)(j * 1.0 / slice), tv, 0.5f, 0.5f, 0, 0, false); } } int io = 0; int bottomVertex = 0; int topVertex = 0; for (int x = 0; x < stack; x++) { bottomVertex = (slice + 1) * x; topVertex = (bottomVertex + slice + 1); for (int y = 0; y < slice; y++) { ind[io++] = bottomVertex; ind[io++] = topVertex; ind[io++] = topVertex + 1; ind[io++] = bottomVertex; ind[io++] = topVertex + 1; ind[io++] = bottomVertex + 1; } } this.vb = new VertexBuffer(typeof(DoubleTextureVertex), this.numvertices, device, Usage.Dynamic, DoubleTextureVertex.Format, Pool.Default); this.vb.SetData(verts, 0, 0); this.ib = new IndexBuffer(typeof(int), this.numindices, device, 0, 0); this.ib.SetData(ind, 0, 0); // Create the vertexdeclaration VertexElement[] vs = new VertexElement[] { new VertexElement(0, 0, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Position, 0), new VertexElement(0, 12, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Normal, 0), new VertexElement(0, 24, DeclarationType.Float2, DeclarationMethod.Default, DeclarationUsage.TextureCoordinate, 0), new VertexElement(0, 32, DeclarationType.Float4, DeclarationMethod.Default, DeclarationUsage.TextureCoordinate, 1), VertexElement.VertexDeclarationEnd }; this.decl = new VertexDeclaration(device, vs); }