public virtual void ComputeViewMatrix() { double lat1 = _latitude.Degrees; double lon1 = _longitude.Degrees; EyeDiff.X = SMath.DegreesToRadians(_latitude.Degrees - lat1); EyeDiff.Y = SMath.DegreesToRadians(_longitude.Degrees - lon1); ReferenceCenter = SMath.SphericalToCartesianV3D( _latitude.Degrees, _longitude.Degrees, WorldRadius); if (World.Settings.Project == Projection.OrthoGraghics) { //lat1 = 0; //lon1 = 0; EyeDiff.X = 0; EyeDiff.Y = 0; } Vector3d defaultPosition = SMath.SphericalToCartesianV3D(lat1, lon1, _worldRadius); m_ViewMatrix = Matrix4d.LookAtRH( defaultPosition, Vector3d.Empty, cameraUpVector); //TODO JHJ 这是干什么的 有什么用 m_ViewMatrix *= Matrix4d.Translation(0, 0, _worldRadius); m_ViewMatrix *= Matrix4d.RotationYawPitchRoll(-EyeDiff.Y, EyeDiff.X, 0); m_ViewMatrix *= Matrix4d.Translation(0, 0, -_worldRadius); m_ViewMatrix *= Matrix4d.RotationYawPitchRoll( 0, -_tilt.Radians, this._heading.Radians); m_ViewMatrix *= Matrix4d.Translation(0, 0, (-this._distance)); if (World.Settings.Project == Projection.Perspective) { m_ViewMatrix *= Matrix4d.RotationZ(this._bank.Radians); } else { m_ViewMatrix *= Matrix4d.RotationZ(this._bank.Radians); } // Extract camera position Matrix4d cam = Matrix4d.Invert(m_ViewMatrix); _position = new Vector3d(cam[3, 0], cam[3, 1], cam[3, 2]); }
/// <summary> /// Calculates latitude/longitude for given screen coordinate. /// </summary> public virtual void PickingRayIntersection( int screenX, int screenY, out Angle latitude, out Angle longitude) { if (m_ProjectionMatrix == null || m_ViewMatrix == null) { latitude = Angle.FromDegrees(0); longitude = Angle.FromDegrees(0); return; } Vector3d v1 = Vector3d.Empty; v1.X = screenX; v1.Y = screenY; v1.Z = viewPort.MinZ; v1.Unproject(viewPort, m_ProjectionMatrix, m_ViewMatrix, m_WorldMatrix); Vector3d v2 = Vector3d.Empty; v2.X = screenX; v2.Y = screenY; v2.Z = viewPort.MaxZ; v2.Unproject(viewPort, m_ProjectionMatrix, m_ViewMatrix, m_WorldMatrix); Vector3d p1 = new Vector3d(v1.X, v1.Y, v1.Z); Vector3d p2 = new Vector3d(v2.X, v2.Y, v2.Z); double a = (p2.X - p1.X) * (p2.X - p1.X) + (p2.Y - p1.Y) * (p2.Y - p1.Y) + (p2.Z - p1.Z) * (p2.Z - p1.Z); double b = 2.0 * ((p2.X - p1.X) * (p1.X) + (p2.Y - p1.Y) * (p1.Y) + (p2.Z - p1.Z) * (p1.Z)); double c = p1.X * p1.X + p1.Y * p1.Y + p1.Z * p1.Z - _worldRadius * _worldRadius; double discriminant = b * b - 4 * a * c; if (discriminant <= 0) { latitude = Angle.NaN; longitude = Angle.NaN; return; } double t1 = ((-1.0) * b - Math.Sqrt(b * b - 4 * a * c)) / (2 * a); Vector3d i1 = new Vector3d(p1.X + t1 * (p2.X - p1.X), p1.Y + t1 * (p2.Y - p1.Y), p1.Z + t1 * (p2.Z - p1.Z)); Vector3d i1t = SMath.CartesianToSpherical(i1.X, i1.Y, i1.Z); Vector3d mousePointer = i1t; latitude = Angle.FromRadians(mousePointer.Y); longitude = Angle.FromRadians(mousePointer.Z); }
public World(string name, Vector3d position, Quaternion4d orientation, System.Windows.Forms.Control control, TerrainAccessor terrainAccessor) { this._name = name; m_worldradius = EarthRadius; this.position = position; this.orientation = orientation; MeterPerDegree = SMath.MeterPerDegree(); this._terrainAccessor = terrainAccessor; this.RenderLayerList = new GeoLayerList(); m_OverlayList = new WidgetRoot(control); }
// 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)); }
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)); } }
/// <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 void Update(double south, double north, double west, double east, double radius1, double radius2) { double scale = radius2 / radius1; SMath.SphericalToCartesianV3D(south, west, radius1, ref this.corners[0]); this.corners[1] = this.corners[0]; this.corners[1].scale(scale); SMath.SphericalToCartesianV3D(south, east, radius1, ref this.corners[2]); this.corners[3] = this.corners[2]; this.corners[3].scale(scale); SMath.SphericalToCartesianV3D(north, west, radius1, ref this.corners[4]); this.corners[5] = this.corners[4]; this.corners[5].scale(scale); SMath.SphericalToCartesianV3D(north, east, radius1, ref this.corners[6]); this.corners[7] = this.corners[6]; this.corners[7].scale(scale); ComputeBoundSphere(); }
/// <summary> /// Sets camera position. /// </summary> /// <param name="lat">Latitude in decimal degrees</param> /// <param name="lon">Longitude in decimal degrees</param> /// <param name="heading">Heading in decimal degrees</param> /// <param name="_altitude">Altitude above ground level in meters</param> /// <param name="tilt">Tilt in decimal degrees</param> /// <param name="bank">Camera bank (roll) in decimal degrees</param> public virtual void SetPosition(double lat, double lon, double heading, double _altitude, double tilt, double bank) { if (double.IsNaN(lat)) { lat = this._latitude.Degrees; } if (double.IsNaN(lon)) { lon = this._longitude.Degrees; } if (double.IsNaN(heading)) { heading = this._heading.Degrees; } if (double.IsNaN(bank)) { bank = this._bank.Degrees; } m_Orientation = Quaternion4d.EulerToQuaternion( SMath.DegreesToRadians(lon), SMath.DegreesToRadians(lat), SMath.DegreesToRadians(heading)); Vector3d p = Quaternion4d.QuaternionToEulerV3D(m_Orientation); _latitude.Radians = p.Y; _longitude.Radians = p.X; _heading.Radians = p.Z; if (!double.IsNaN(tilt)) { Tilt = Angle.FromDegrees(tilt); } if (!double.IsNaN(_altitude)) { this.Altitude = _altitude; } this.Bank = Angle.FromDegrees(bank); }
public override void SetPosition(double lat, double lon, double heading, double _altitude, double tilt, double bank) { if (double.IsNaN(lat)) { lat = this._latitude.Degrees; } if (double.IsNaN(lon)) { lon = this._longitude.Degrees; } if (double.IsNaN(heading)) { heading = this._heading.Degrees; } if (double.IsNaN(bank)) { bank = _targetBank.Degrees; } this._targetOrientation = Quaternion4d.EulerToQuaternion( SMath.DegreesToRadians(lon), SMath.DegreesToRadians(lat), SMath.DegreesToRadians(heading)); Vector3d v = Quaternion4d.QuaternionToEulerV3D(this._targetOrientation); this._targetLatitude.Radians = v.Y; this._targetLongitude.Radians = v.X; this._targetHeading.Radians = v.Z; if (!double.IsNaN(tilt)) { this.Tilt = Angle.FromDegrees(tilt); } if (!double.IsNaN(_altitude)) { Altitude = _altitude; } this.Bank = Angle.FromDegrees(bank); }
/// <summary> /// 输出对应插值的Point3d(纬度,经度,高程)。高程值为当前经纬度下的最高精度值。 /// 空间插值,通过首尾两点的经纬度计算,由f来控制此点的次序,f=n/N;在0~1之间 /// </summary> /// <param name="Args"></param> /// <param name="f"></param> /// <param name="lat1"></param> /// <param name="lon1"></param> /// <param name="lat2"></param> /// <param name="lon2"></param> /// <returns></returns> public static Vector3d CacuInterGCPoint(float f, Angle lat1, Angle lon1, Angle lat2, Angle lon2) { Angle lat; Angle lon; Double Z = new double(); Angle d = SMath.ApproxAngularDistance(lat1.Radians, lon1.Radians, lat2.Radians, lon2.Radians); 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); lat = Angle.FromRadians(Math.Atan2(z, Math.Sqrt(x * x + y * y))); lon = Angle.FromRadians(Math.Atan2(y, x)); Z = 0; Vector3d p = new Vector3d(lat.Degrees, lon.Degrees, Z); return(p); }
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); }