/// <summary> /// Tests if the bounding box specified intersects with or is fully contained in the frustum. /// </summary> /// <returns>true when the box intersects with the frustum.</returns> public bool Intersects(BoundingBox bb) { Point3d v; // Optimize by always checking bounding sphere first if (!IntersectsOne(bb.boundsphere)) return false; foreach (Plane2d p in this.planes) { v.X = p.A; v.Y = p.B; v.Z = p.C; bool isInside = false; for(int i = 0; i < 8; i++) { if(Point3d.dot(v, bb.corners[i]) + p.D >= 0) { isInside = true; break; } } if(!isInside) return false; } return true; }
/// <summary> /// Tests if the view frustum fully contains the bounding box. /// </summary> /// <returns>true when the box is complete enclosed by the frustum.</returns> public bool Contains(BoundingBox bb) { //Code taken from Flip Code Article: // http://www.flipcode.com/articles/article_frustumculling.shtml int iTotalIn = 0; foreach (Plane p in this.planes) { int iInCount = 8; int iPtIn = 1; // TODO: Modify bounding box and only check 2 corners. for (int i = 0; i < 8; i++) { if (Vector3.Dot(new Vector3(p.A, p.B, p.C), bb.corners[i]) + p.D < 0) { iPtIn = 0; --iInCount; } } if (iInCount == 0) { return false; } iTotalIn += iPtIn; } if (iTotalIn == 6) { return true; } return false; }
internal ProjectedVectorTile( GeographicBoundingBox geographicBoundingBox, ProjectedVectorRenderer parentLayer ) { m_geographicBoundingBox = geographicBoundingBox; m_parentProjectedLayer = parentLayer; BoundingBox = new BoundingBox( (float)geographicBoundingBox.South, (float)geographicBoundingBox.North, (float)geographicBoundingBox.West, (float)geographicBoundingBox.East, (float)(parentLayer.World.EquatorialRadius + geographicBoundingBox.MinimumAltitude), (float)(parentLayer.World.EquatorialRadius + geographicBoundingBox.MaximumAltitude + 300000f)); }
public ShapeTile( GeographicBoundingBox geoBB, ShapeTileArgs shapeTileArgs ) { m_GeoBB = geoBB; m_ShapeTileArgs = shapeTileArgs; BoundingBox = new BoundingBox( (float)geoBB.South, (float)geoBB.North, (float)geoBB.West, (float)geoBB.East, (float)m_ShapeTileArgs.LayerRadius, (float)m_ShapeTileArgs.LayerRadius + 300000f); }
Vector3[] sphericalCoordinates = new Vector3[0]; // x = lat, y = lon, z = height /// <summary> /// Initializes a new instance of the <see cref= "T:WorldWind.Renderable.PathLine"/> class. /// </summary> /// <param name="name"></param> /// <param name="parentWorld"></param> /// <param name="terrainfileName"></param> /// <param name="heightAboveSurface"></param> /// <param name="lineColor"></param> public PathLine(string name, World parentWorld, string terrainfileName, float heightAboveSurface, System.Drawing.Color lineColor) : base(name, parentWorld.Position, Quaternion.RotationYawPitchRoll(0,0,0)) { this._parentWorld = parentWorld; //this.terrainManager = terrainManager; this.terrainFileName = terrainfileName; this.heightAboveSurface = heightAboveSurface; this.lineColor = lineColor.ToArgb(); if(this.terrainFileName == null) { this.isInitialized = true; this.isLoaded = true; this.linePoints = new CustomVertex.PositionColored[0]; return; } FileInfo inFile = new FileInfo(this.terrainFileName); if(!inFile.Exists) { this.isInitialized = true; this.isLoaded = true; this.linePoints = new CustomVertex.PositionColored[0]; return; } if(inFile.FullName.IndexOf('_') == -1) { return; } string[] parsedFileName = inFile.Name.Replace(".wwb","").Split('_'); if(parsedFileName.Length < 5) { return; } else { this.north = (float)Int32.Parse(parsedFileName[1], CultureInfo.InvariantCulture); this.south = (float)Int32.Parse(parsedFileName[2], CultureInfo.InvariantCulture); this.west = (float)Int32.Parse(parsedFileName[3], CultureInfo.InvariantCulture); this.east = (float)Int32.Parse(parsedFileName[4], CultureInfo.InvariantCulture); } this.boundingBox = new BoundingBox( this.south, this.north, this.west, this.east, (float)this._parentWorld.EquatorialRadius, (float)this._parentWorld.EquatorialRadius + this.heightAboveSurface ); }
public void AddPointToPath(float lat, float lon, float alt) { Vector3 newCoord = new Vector3(lat, lon, alt); this.sphericalCoordinates.Add(newCoord); if (this.north < newCoord.X) this.north = newCoord.X; if (this.east < newCoord.Y) this.east = newCoord.Y; if (this.south > newCoord.X) this.south = newCoord.X; if (this.west > newCoord.Y) this.west = newCoord.Y; this.boundingBox = new BoundingBox( this.south, this.north, this.west, this.east, (float)this._parentWorld.EquatorialRadius, (float)(this._parentWorld.EquatorialRadius + this.verticalExaggeration * alt)); lastUpdatedPosition.X = lat; this.isLoaded = true; this.isInitialized = false; this.m_needsUpdate = true; }
public void Load(DrawArgs drawArgs) { try { #region JHU CHANGES if (this.sphericalCoordinates == null) this.sphericalCoordinates = new ArrayList(); #endregion if(this._dataArchiveReader == null) { if(this.terrainFileName == null) { this.isInitialized = true; return; } FileInfo inFile = new FileInfo(this.terrainFileName); if(!inFile.Exists) { this.isInitialized = true; return; } using( BufferedStream fs = new BufferedStream(inFile.OpenRead()) ) using( BinaryReader br = new BinaryReader(fs) ) { int numCoords = br.ReadInt32(); #region JHU CHANGES // this.sphericalCoordinates = new Vector3[numCoords]; // this.sphericalCoordinates[0].X = br.ReadSingle(); // this.sphericalCoordinates[0].Y = br.ReadSingle(); // // this.north = this.sphericalCoordinates[0].X; // this.south = this.sphericalCoordinates[0].X; // this.west = this.sphericalCoordinates[0].Y; // this.east = this.sphericalCoordinates[0].Y; Vector3 newCoord = new Vector3(); newCoord.X = br.ReadSingle(); newCoord.Y = br.ReadSingle(); sphericalCoordinates.Add(newCoord); for (int i = 1; i < numCoords; i++) { // this.sphericalCoordinates[i].X = br.ReadSingle(); // this.sphericalCoordinates[i].Y = br.ReadSingle(); // // if (this.north < this.sphericalCoordinates[i].X) // this.north = this.sphericalCoordinates[i].X; // if (this.east < this.sphericalCoordinates[i].Y) // this.east = this.sphericalCoordinates[i].Y; // if (this.south > this.sphericalCoordinates[i].X) // this.south = this.sphericalCoordinates[i].X; // if (this.west > this.sphericalCoordinates[i].Y) // this.west = this.sphericalCoordinates[i].Y; newCoord.X = br.ReadSingle(); newCoord.Y = br.ReadSingle(); sphericalCoordinates.Add(newCoord); if (this.north < newCoord.X) this.north = newCoord.X; if (this.east < newCoord.Y) this.east = newCoord.Y; if (this.south > newCoord.X) this.south = newCoord.X; if (this.west > newCoord.Y) this.west = newCoord.Y; } #endregion } this.boundingBox = new BoundingBox( this.south, this.north, this.west, this.east, (float)this._parentWorld.EquatorialRadius, (float)(this._parentWorld.EquatorialRadius + this.verticalExaggeration * heightAboveSurface)); } else { this._dataArchiveReader.BaseStream.Seek(this._fileOffset, SeekOrigin.Begin); int numCoords = this._dataArchiveReader.ReadInt32(); byte numElements = this._dataArchiveReader.ReadByte(); #region JHU CHANGES // this.sphericalCoordinates = new Vector3[numCoords]; Vector3 newCoord = new Vector3(); for(int i = 0; i < numCoords; i++) { // this.sphericalCoordinates[i].X = (float)this._dataArchiveReader.ReadDouble(); // this.sphericalCoordinates[i].Y = (float)this._dataArchiveReader.ReadDouble(); // if(numElements == 3) // this.sphericalCoordinates[i].Z = this._dataArchiveReader.ReadInt16(); newCoord.X = (float)this._dataArchiveReader.ReadDouble(); newCoord.Y = (float)this._dataArchiveReader.ReadDouble(); if(numElements == 3) newCoord.Z = this._dataArchiveReader.ReadInt16(); sphericalCoordinates.Add(newCoord); } #endregion } } catch(Exception caught) { Log.Write( caught ); } this.isLoaded = true; }
/// <summary> /// Initializes a new instance of the <see cref= "T:WorldWind.Renderable.TerrainPath"/> class. /// </summary> /// <param name="name"></param> /// <param name="parentWorld"></param> /// <param name="minDisplayAltitude"></param> /// <param name="maxDisplayAltitude"></param> /// <param name="dataArchiveReader"></param> /// <param name="fileOffset"></param> /// <param name="fileSize"></param> /// <param name="north"></param> /// <param name="south"></param> /// <param name="east"></param> /// <param name="west"></param> /// <param name="heightAboveSurface"></param> /// <param name="lineColor"></param> /// <param name="terrainAccessor"></param> public JHU_TerrainPath( string name, World parentWorld, double minDisplayAltitude, double maxDisplayAltitude, BinaryReader dataArchiveReader, long fileOffset, long fileSize, double north, double south, double east, double west, float heightAboveSurface, System.Drawing.Color lineColor, TerrainAccessor terrainAccessor) : base(name, parentWorld.Position, Quaternion.RotationYawPitchRoll(0,0,0)) { this._parentWorld = parentWorld; this._minDisplayAltitude = minDisplayAltitude; this._maxDisplayAltitude = maxDisplayAltitude; this._dataArchiveReader = dataArchiveReader; this._fileOffset = fileOffset; this._fileSize = fileSize; this.heightAboveSurface = heightAboveSurface; this.lineColor = lineColor.ToArgb(); this._terrainAccessor = terrainAccessor; this.sphericalCoordinates = new ArrayList(); this.north = (float)north; this.south = (float)south; this.west = (float)west; this.east = (float)east; this.RenderPriority = RenderPriority.LinePaths; this.boundingBox = new BoundingBox( this.south, this.north, this.west, this.east, (float)this._parentWorld.EquatorialRadius, (float)(this._parentWorld.EquatorialRadius + this.verticalExaggeration * heightAboveSurface)); }
/// <summary> /// Tests if the bounding box specified intersects with or is fully contained in the frustum. /// </summary> /// <returns>true when the box intersects with the frustum.</returns> public bool Intersects(BoundingBox bb) { foreach(Plane p in this.planes) { Vector3 v = new Vector3(p.A,p.B,p.C); bool isInside = false; // TODO: Modify bounding box and only check 2 corners. for(int i = 0; i < 8; i++) { if(Vector3.Dot(v, bb.corners[i]) + p.D >= 0) { isInside = true; break; } } if(!isInside) return false; } return true; }
public PolygonFeature( string name, World parentWorld, LinearRing outerRing, LinearRing[] innerRings, System.Drawing.Color polygonColor) : base(name, parentWorld) { RenderPriority = WorldWind.Renderable.RenderPriority.LinePaths; m_outerRing = outerRing; m_innerRings = innerRings; m_polygonColor = polygonColor; double minY = double.MaxValue; double maxY = double.MinValue; double minX = double.MaxValue; double maxX = double.MinValue; double minZ = double.MaxValue; double maxZ = double.MinValue; for(int i = 0; i < m_outerRing.Points.Length; i++) { if(m_outerRing.Points[i].X < minX) minX = m_outerRing.Points[i].X; if(m_outerRing.Points[i].X > maxX) maxX = m_outerRing.Points[i].X; if(m_outerRing.Points[i].Y < minY) minY = m_outerRing.Points[i].Y; if(m_outerRing.Points[i].Y > maxY) maxY = m_outerRing.Points[i].Y; if(m_outerRing.Points[i].Z < minZ) minZ = m_outerRing.Points[i].Z; if(m_outerRing.Points[i].Z > maxZ) maxZ = m_outerRing.Points[i].Z; } // set a uniform Z for all the points for(int i = 0; i < m_outerRing.Points.Length; i++) { if(m_outerRing.Points[i].Z != maxZ) m_outerRing.Points[i].Z = maxZ; } if(m_innerRings != null && m_innerRings.Length > 0) { for(int n = 0; n < m_innerRings.Length; n++) { for(int i = 0; i < m_innerRings[n].Points.Length; i++) { if(m_innerRings[n].Points[i].Z != maxZ) m_innerRings[n].Points[i].Z = maxZ; } } } m_geographicBoundingBox = new GeographicBoundingBox(maxY, minY, minX, maxX, minZ, maxZ); minZ += parentWorld.EquatorialRadius; maxZ += parentWorld.EquatorialRadius; BoundingBox = new BoundingBox( (float)minY, (float)maxY, (float)minX, (float)maxX, (float)minZ, (float)maxZ); }
/// <summary> /// Creates a new <see cref="SurfaceTile"/> instance. /// </summary> /// <param name="north">North. (in degrees)</param> /// <param name="south">South. (in degrees)</param> /// <param name="west">West. (in degrees)</param> /// <param name="east">East. (in degrees)</param> /// <param name="level">Level.</param> /// <param name="parentWorldSurfaceRenderer">Parent world surface renderer.</param> public SurfaceTile(double north, double south, double west, double east, int level, WorldSurfaceRenderer parentWorldSurfaceRenderer) { m_North = north; m_South = south; m_West = west; m_East = east; m_Level = level; m_ParentWorldSurfaceRenderer = parentWorldSurfaceRenderer; float scale = 1.1f; Vector3 v = MathEngine.SphericalToCartesian(Angle.FromDegrees(south), Angle.FromDegrees(west), m_ParentWorldSurfaceRenderer.ParentWorld.EquatorialRadius + m_ParentWorldSurfaceRenderer.DistanceAboveSeaLevel); Vector3 v0 = new Vector3((float) v.X, (float) v.Y, (float) v.Z); Vector3 v1 = Vector3.Scale(v0, scale); v = MathEngine.SphericalToCartesian(Angle.FromDegrees(south), Angle.FromDegrees(east), m_ParentWorldSurfaceRenderer.ParentWorld.EquatorialRadius + m_ParentWorldSurfaceRenderer.DistanceAboveSeaLevel); Vector3 v2 = new Vector3((float) v.X, (float) v.Y, (float) v.Z); Vector3 v3 = Vector3.Scale(v2, scale); v = MathEngine.SphericalToCartesian(Angle.FromDegrees(north), Angle.FromDegrees(west), m_ParentWorldSurfaceRenderer.ParentWorld.EquatorialRadius + m_ParentWorldSurfaceRenderer.DistanceAboveSeaLevel); Vector3 v4 = new Vector3((float) v.X, (float) v.Y, (float) v.Z); Vector3 v5 = Vector3.Scale(v4, scale); v = MathEngine.SphericalToCartesian(Angle.FromDegrees(north), Angle.FromDegrees(east), m_ParentWorldSurfaceRenderer.ParentWorld.EquatorialRadius + m_ParentWorldSurfaceRenderer.DistanceAboveSeaLevel); Vector3 v6 = new Vector3((float) v.X, (float) v.Y, (float) v.Z); Vector3 v7 = Vector3.Scale(v6, scale); m_BoundingBox = new BoundingBox(v0, v1, v2, v3, v4, v5, v6, v7); int thisVertexDensityElevatedPlus2 = ((int) m_ParentWorldSurfaceRenderer.SamplesPerTile/2 + 2); m_IndicesElevated = new short[2*thisVertexDensityElevatedPlus2*thisVertexDensityElevatedPlus2*3]; for (int i = 0; i < thisVertexDensityElevatedPlus2; i++) { int elevated_idx = (2*3*i*thisVertexDensityElevatedPlus2); for (int j = 0; j < thisVertexDensityElevatedPlus2; j++) { m_IndicesElevated[elevated_idx] = (short) (i*(thisVertexDensityElevatedPlus2 + 1) + j); m_IndicesElevated[elevated_idx + 1] = (short) ((i + 1)*(thisVertexDensityElevatedPlus2 + 1) + j); m_IndicesElevated[elevated_idx + 2] = (short) (i*(thisVertexDensityElevatedPlus2 + 1) + j + 1); m_IndicesElevated[elevated_idx + 3] = (short) (i*(thisVertexDensityElevatedPlus2 + 1) + j + 1); m_IndicesElevated[elevated_idx + 4] = (short) ((i + 1)*(thisVertexDensityElevatedPlus2 + 1) + j); m_IndicesElevated[elevated_idx + 5] = (short) ((i + 1)*(thisVertexDensityElevatedPlus2 + 1) + j + 1); elevated_idx += 6; } } }
/// <summary> /// Disposes this instance. Releases any resources from the graphics device, also disposes of "child" surface tiles. /// </summary> public void Dispose() { m_Initialized = false; m_BoundingBox = null; if (m_Device != null) { m_Device.DeviceReset -= new EventHandler(OnDeviceReset); m_Device.Disposing -= new EventHandler(OnDeviceDispose); OnDeviceDispose(m_Device, null); } if (m_NorthWestChild != null) { m_NorthWestChild.Dispose(); m_NorthWestChild = null; } if (m_NorthEastChild != null) { m_NorthEastChild.Dispose(); m_NorthEastChild = null; } if (m_SouthWestChild != null) { m_SouthWestChild.Dispose(); m_SouthWestChild = null; } if (m_SouthEastChild != null) { m_SouthEastChild.Dispose(); m_SouthEastChild = null; } }
/// <summary> /// Build the elevated terrain mesh /// </summary> protected virtual void CreateElevatedMesh() { isDownloadingTerrain = true; // Get height data with one extra sample around the tile double degreePerSample = LatitudeSpan / vertexCountElevated; TerrainTile tile = quadTileSet.World.TerrainAccessor.GetElevationArray(north + degreePerSample, south - degreePerSample, west - degreePerSample, east + degreePerSample, vertexCountElevated + 3); float[,] heightData = tile.ElevationData; int vertexCountElevatedPlus3 = vertexCountElevated / 2 + 3; int totalVertexCount = vertexCountElevatedPlus3 * vertexCountElevatedPlus3; northWestVertices = new CustomVertex.PositionNormalTextured[totalVertexCount]; southWestVertices = new CustomVertex.PositionNormalTextured[totalVertexCount]; northEastVertices = new CustomVertex.PositionNormalTextured[totalVertexCount]; southEastVertices = new CustomVertex.PositionNormalTextured[totalVertexCount]; double layerRadius = (double)quadTileSet.LayerRadius; // Calculate mesh base radius (bottom vertices) // Find minimum elevation to account for possible bathymetry float minimumElevation = float.MaxValue; float maximumElevation = float.MinValue; foreach (float height in heightData) { if (height < minimumElevation) minimumElevation = height; if (height > maximumElevation) maximumElevation = height; } minimumElevation *= verticalExaggeration; maximumElevation *= verticalExaggeration; if (minimumElevation > maximumElevation) { // Compensate for negative vertical exaggeration minimumElevation = maximumElevation; maximumElevation = minimumElevation; } CreateElevatedMesh(ChildLocation.NorthWest, northWestVertices, heightData); CreateElevatedMesh(ChildLocation.SouthWest, southWestVertices, heightData); CreateElevatedMesh(ChildLocation.NorthEast, northEastVertices, heightData); CreateElevatedMesh(ChildLocation.SouthEast, southEastVertices, heightData); // --- Make bounding box slightly larger so the tile won't blink in and out near the edges --- BoundingBox = new BoundingBox(south - 1.0, north + 1.0, west - 1.0, east + 1.0, layerRadius, layerRadius + 10000.0 * this.verticalExaggeration); quadTileSet.IsDownloadingElevation = false; // Build common set of indexes for the 4 child meshes int vertexCountElevatedPlus2 = vertexCountElevated / 2 + 2; vertexIndexes = new short[2 * vertexCountElevatedPlus2 * vertexCountElevatedPlus2 * 3]; int elevated_idx = 0; for (int i = 0; i < vertexCountElevatedPlus2; i++) { for (int j = 0; j < vertexCountElevatedPlus2; j++) { vertexIndexes[elevated_idx++] = (short)(i * vertexCountElevatedPlus3 + j); vertexIndexes[elevated_idx++] = (short)((i + 1) * vertexCountElevatedPlus3 + j); vertexIndexes[elevated_idx++] = (short)(i * vertexCountElevatedPlus3 + j + 1); vertexIndexes[elevated_idx++] = (short)(i * vertexCountElevatedPlus3 + j + 1); vertexIndexes[elevated_idx++] = (short)((i + 1) * vertexCountElevatedPlus3 + j); vertexIndexes[elevated_idx++] = (short)((i + 1) * vertexCountElevatedPlus3 + j + 1); } } calculate_normals(ref northWestVertices, vertexIndexes); calculate_normals(ref southWestVertices, vertexIndexes); calculate_normals(ref northEastVertices, vertexIndexes); calculate_normals(ref southEastVertices, vertexIndexes); isDownloadingTerrain = false; }
// End New Cache /// <summary> /// Initializes a new instance of the <see cref= "T:WorldWind.Renderable.QuadTile"/> class. /// </summary> /// <param name="_south"></param> /// <param name="_north"></param> /// <param name="_west"></param> /// <param name="_east"></param> /// <param name="_level"></param> /// <param name="quadTileSet"></param> internal QuadTile(double _south, double _north, double _west, double _east, int _level, QuadTileSet quadTileSet) { this.south = _south; this.north = _north; this.west = _west; this.east = _east; centerLatitude = Angle.FromDegrees(0.5f * (north + south)); centerLongitude = Angle.FromDegrees(0.5f * (west + east)); LatitudeSpan = Math.Abs(north - south); LongitudeSpan = Math.Abs(east - west); this.level = _level; this.quadTileSet = quadTileSet; // --- Make bounding box slightly larger so the tile won't blink in and out near the edges --- BoundingBox = new BoundingBox(south - LatitudeSpan / 8.0, north + LatitudeSpan / 8.0, west - LongitudeSpan / 8.0, east + LongitudeSpan / 8.0, quadTileSet.LayerRadius, quadTileSet.LayerRadius + 300000.0); //localOrigin = BoundingBox.CalculateCenter(); localOrigin = MathEngine.SphericalToCartesian(centerLatitude, centerLongitude, quadTileSet.LayerRadius); // To avoid gaps between neighbouring tiles truncate the origin to // a number that doesn't get rounded. (nearest 10km) localOrigin.X = (float)(Math.Round(localOrigin.X / 10000) * 10000); localOrigin.Y = (float)(Math.Round(localOrigin.Y / 10000) * 10000); localOrigin.Z = (float)(Math.Round(localOrigin.Z / 10000) * 10000); row = MathEngine.GetRowFromLatitude((north + south) / 2.0, north - south); col = MathEngine.GetColFromLongitude((east + west) / 2.0, east - west); downloadRequests = new List<GeoSpatialDownloadRequest>(); key = string.Format("{0,4}", this.level) + "_" + string.Format("{0,4}", this.col) + string.Format("{0,4}", this.row) + this.quadTileSet.Name + this.quadTileSet.ParentList.Name; quadTileSet.ImageStores[0].GetProjectionCorners(this, out UL, out UR, out LL, out LR); }
public void Load() { try { if(this.terrainFileName == null && this._dataArchiveReader == null) { this.isInitialized = true; return; } sphericalCoordinates = GetSphericalCoordinates(ref north, ref south, ref west, ref east); this.boundingBox = new BoundingBox( this.south, this.north, this.west, this.east, (float)this._parentWorld.EquatorialRadius, (float)(this._parentWorld.EquatorialRadius + this.verticalExaggeration * heightAboveSurface)); } catch(Exception caught) { Log.Write( caught ); } this.isLoaded = true; }