From 01d4286569ed799edf6ce81abf17eea8ecb4ba2e Mon Sep 17 00:00:00 2001 From: Joel Aaron Cohen Date: Thu, 13 Dec 2007 08:28:47 -0500 Subject: [PATCH] Update to Worldwind release 0.4.1 --- config/worldwind.properties | 3 +- gov/nasa/worldwind/Version.java | 6 +- gov/nasa/worldwind/WorldWind.java | 27 +- gov/nasa/worldwind/avlist/AVKey.java | 4 +- gov/nasa/worldwind/awt/KeyPollTimer.java | 2 +- gov/nasa/worldwind/examples/StatusBar.java | 24 +- .../globes/EllipsoidRectangularTessellator.java | 1069 -------------------- gov/nasa/worldwind/util/BasicNetworkStatus.java | 149 ++- gov/nasa/worldwind/util/NetworkStatus.java | 34 +- gov/nasa/worldwind/view/View.java | 239 ----- gov/nasa/worldwind/view/ViewStateIterator.java | 41 - 11 files changed, 185 insertions(+), 1413 deletions(-) delete mode 100644 gov/nasa/worldwind/globes/EllipsoidRectangularTessellator.java delete mode 100644 gov/nasa/worldwind/view/View.java delete mode 100644 gov/nasa/worldwind/view/ViewStateIterator.java diff --git a/config/worldwind.properties b/config/worldwind.properties index 68c791e..9d20c66 100644 --- a/config/worldwind.properties +++ b/config/worldwind.properties @@ -1,5 +1,5 @@ # Default World Wind Configuration Properties -# @version $Id: worldwind.properties 3632 2007-11-28 03:28:17Z tgaskins $ +# @version $Id: worldwind.properties 3735 2007-12-06 02:20:43Z tgaskins $ # Specify configuration values here to override World Wind's default values. # Lines starting with # are comments and ignored by World Wind. # @@ -46,3 +46,4 @@ gov.nasa.worldwind.avkey.ElevationTileCacheSize=5000000 gov.nasa.worldwind.avkey.SectorGeometryCacheSize=20000000 gov.nasa.worldwind.avkey.TextureTileCacheSize=3000000 gov.nasa.worldwind.avkey.PlacenameLayerCacheSize=2000000 +gov.nasa.worldwind.avkey.OfflineMode=false diff --git a/gov/nasa/worldwind/Version.java b/gov/nasa/worldwind/Version.java index 685b855..fc21b79 100644 --- a/gov/nasa/worldwind/Version.java +++ b/gov/nasa/worldwind/Version.java @@ -8,16 +8,16 @@ package gov.nasa.worldwind; /** * @author tag - * @version $Id: Version.java 3278 2007-10-10 23:21:14Z tgaskins $ + * @version $Id: Version.java 3734 2007-12-06 01:26:24Z tgaskins $ */ public class Version { private static final String MAJOR_VALUE = "0"; private static final String MINOR_VALUE = "4"; - private static final String DOT_VALUE = "0"; + private static final String DOT_VALUE = "1"; private static final String versionNumber = MAJOR_VALUE + "." + MINOR_VALUE + "." + DOT_VALUE; - private static final String versionName = "NASA World Wind Java Alpha 4"; + private static final String versionName = "NASA World Wind Java Alpha 4.1"; public static String getVersion() { diff --git a/gov/nasa/worldwind/WorldWind.java b/gov/nasa/worldwind/WorldWind.java index f003770..8126037 100644 --- a/gov/nasa/worldwind/WorldWind.java +++ b/gov/nasa/worldwind/WorldWind.java @@ -17,12 +17,12 @@ import java.beans.PropertyChangeListener; /** * @author Tom Gaskins - * @version $Id: WorldWind.java 3696 2007-12-04 01:52:16Z tgaskins $ + * @version $Id: WorldWind.java 3735 2007-12-06 02:20:43Z tgaskins $ */ public final class WorldWind { public static final String SHUTDOWN_EVENT = "gov.nasa.worldwind.ShutDown"; - + private static WorldWind instance = new WorldWind(); private WWObjectImpl wwo; @@ -106,6 +106,29 @@ public final class WorldWind } /** + * Indicates whether World Wind will attempt to connect to the network to retrieve data or for other reasons. + * + * @return true if World Wind is in off-line mode, false if not. + * @see NetworkStatus + */ + public boolean isOfflineMode() + { + return getNetworkStatus().isOfflineMode(); + } + + /** + * Indicate whether World Wind should attempt to connect to the network to retrieve data or for other reasons. The + * default value for this attribute is false, indicating that the network should be used. + * + * @param offlineMode true if World Wind should use the network, false otherwise + * @see NetworkStatus + */ + public void setOfflineMode(boolean offlineMode) + { + getNetworkStatus().setOfflineMode(offlineMode); + } + + /** * @param className the full name, including package names, of the component to create * @return the new component * @throws WWRuntimeException if the Object could not be created diff --git a/gov/nasa/worldwind/avlist/AVKey.java b/gov/nasa/worldwind/avlist/AVKey.java index ecc06d0..6829d96 100644 --- a/gov/nasa/worldwind/avlist/AVKey.java +++ b/gov/nasa/worldwind/avlist/AVKey.java @@ -8,7 +8,7 @@ package gov.nasa.worldwind.avlist; /** * @author Tom Gaskins - * @version $Id: AVKey.java 3598 2007-11-21 03:08:02Z tgaskins $ + * @version $Id: AVKey.java 3735 2007-12-06 02:20:43Z tgaskins $ */ public interface AVKey // TODO: Eliminate unused constants, if any { @@ -61,6 +61,8 @@ public interface AVKey // TODO: Eliminate unused constants, if any final String NUM_EMPTY_LEVELS = "gov.nasa.worldwind.avkey.NumEmptyLevels"; final String NUM_LEVELS = "gov.nasa.worldwind.avkey.NumLevels"; + final String OFFLINE_MODE = "gov.nasa.worldwind.avkey.OfflineMode"; + final String PICKED_OBJECT = "gov.nasa.worldwind.avkey.PickedObject"; final String PICKED_OBJECT_ID = "gov.nasa.worldwind.avkey.PickedObject.ID"; final String PICKED_OBJECT_PARENT_LAYER = "gov.nasa.worldwind.avkey.PickedObject.ParentLayer"; diff --git a/gov/nasa/worldwind/awt/KeyPollTimer.java b/gov/nasa/worldwind/awt/KeyPollTimer.java index af65438..947d119 100644 --- a/gov/nasa/worldwind/awt/KeyPollTimer.java +++ b/gov/nasa/worldwind/awt/KeyPollTimer.java @@ -12,7 +12,7 @@ import java.beans.*; /** * @author dcollins - * @version $Id: KeyPollTimer.java 3696 2007-12-04 01:52:16Z tgaskins $ + * @version $Id: KeyPollTimer.java 3704 2007-12-04 17:49:12Z tgaskins $ */ class KeyPollTimer implements java.awt.event.KeyListener { diff --git a/gov/nasa/worldwind/examples/StatusBar.java b/gov/nasa/worldwind/examples/StatusBar.java index b98fead..1f61f39 100644 --- a/gov/nasa/worldwind/examples/StatusBar.java +++ b/gov/nasa/worldwind/examples/StatusBar.java @@ -16,7 +16,7 @@ import java.awt.*; /** * @author tag - * @version $Id: StatusBar.java 3503 2007-11-14 05:48:29Z tgaskins $ + * @version $Id: StatusBar.java 3735 2007-12-06 02:20:43Z tgaskins $ */ public class StatusBar extends JPanel implements PositionListener, RenderingListener { @@ -25,6 +25,7 @@ public class StatusBar extends JPanel implements PositionListener, RenderingList private final JLabel lonDisplay = new JLabel("Off globe"); private final JLabel altDisplay = new JLabel(""); private final JLabel eleDisplay = new JLabel(""); + private boolean showNetworkStatus = true; public StatusBar() { @@ -51,19 +52,25 @@ public class StatusBar extends JPanel implements PositionListener, RenderingList { public void actionPerformed(java.awt.event.ActionEvent actionEvent) { + if (!showNetworkStatus) + { + if (heartBeat.getText().length() > 0) + heartBeat.setText(""); + return; + } + if (WorldWind.getNetworkStatus().isNetworkUnavailable()) { heartBeat.setText("No Network"); heartBeat.setForeground(new java.awt.Color(255, 0, 0, 255)); -// System.out.println("network UNAVAILABLE"); return; } -// System.out.println("network available"); java.awt.Color color = heartBeat.getForeground(); int alpha = color.getAlpha(); if (WorldWind.getRetrievalService().hasActiveTasks()) { + heartBeat.setText("Downloading"); if (alpha == 255) alpha = 255; else @@ -73,7 +80,6 @@ public class StatusBar extends JPanel implements PositionListener, RenderingList { alpha = Math.max(0, alpha - 20); } - heartBeat.setText("Downloading"); heartBeat.setForeground(new java.awt.Color(255, 0, 0, alpha)); } }); @@ -97,6 +103,16 @@ public class StatusBar extends JPanel implements PositionListener, RenderingList this.eventSource = newEventSource; } + public boolean isShowNetworkStatus() + { + return showNetworkStatus; + } + + public void setShowNetworkStatus(boolean showNetworkStatus) + { + this.showNetworkStatus = showNetworkStatus; + } + public void moved(PositionEvent event) { this.handleCursorPositionChange(event); diff --git a/gov/nasa/worldwind/globes/EllipsoidRectangularTessellator.java b/gov/nasa/worldwind/globes/EllipsoidRectangularTessellator.java deleted file mode 100644 index e4dcc83..0000000 --- a/gov/nasa/worldwind/globes/EllipsoidRectangularTessellator.java +++ /dev/null @@ -1,1069 +0,0 @@ -/* -Copyright (C) 2001, 2006 United States Government -as represented by the Administrator of the -National Aeronautics and Space Administration. -All Rights Reserved. -*/ -package gov.nasa.worldwind.globes; - -import com.sun.opengl.util.BufferUtil; -import gov.nasa.worldwind.*; -import gov.nasa.worldwind.avlist.AVKey; -import gov.nasa.worldwind.cache.*; -import gov.nasa.worldwind.geom.*; -import gov.nasa.worldwind.pick.*; -import gov.nasa.worldwind.render.DrawContext; -import gov.nasa.worldwind.util.Logging; -import gov.nasa.worldwind.view.View; - -import javax.media.opengl.GL; -import java.nio.*; -import java.util.*; - -/** - * @author tag - * @version $Id: EllipsoidRectangularTessellator.java 3210 2007-10-06 22:14:23Z tgaskins $ - */ -public class EllipsoidRectangularTessellator extends WWObjectImpl implements Tessellator -{ - // TODO: Make all this configurable - private static final int DEFAULT_DENSITY = 24; - private static final double DEFAULT_LOG10_RESOLUTION_TARGET = 1.3; - private static final int DEFAULT_MAX_LEVEL = 12; - private static final int DEFAULT_NUM_LAT_SUBDIVISIONS = 5; - private static final int DEFAULT_NUM_LON_SUBDIVISIONS = 10; - - private static class RenderInfo - { - private final int density; - private final Vec4 referenceCenter; - private final DoubleBuffer vertices; - private final DoubleBuffer texCoords; - private final IntBuffer indices; - private final int resolution; - - private RenderInfo(int density, DoubleBuffer vertices, DoubleBuffer texCoords, Vec4 refCenter, int resolution) - { - this.density = density; - this.vertices = vertices; - this.texCoords = texCoords; - this.referenceCenter = refCenter; - this.indices = RectTile.getIndices(this.density); - this.resolution = resolution; - } - - private long getSizeInBytes() - { - // Texture coordinates are shared among all tiles of the same density, so do not count towards size. - // 8 references, doubles in buffer. - return 8 * 4 + (this.vertices.limit()) * Double.SIZE; - } - } - - private static class CacheKey - { - private final Sector sector; - private int resolution; - private final double verticalExaggeration; - private int density; - - private CacheKey(RectTile tile, int resolution, double verticalExaggeration, int density) - { - this.sector = tile.sector; - this.resolution = resolution; - this.verticalExaggeration = verticalExaggeration; - this.density = density; - } - - @Override - public String toString() - { - return "density " + this.density + " ve " + this.verticalExaggeration + " resolution " + this.resolution - + " sector " + this.sector; - } - - public boolean equals(Object o) - { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - - CacheKey cacheKey = (CacheKey) o; - - if (density != cacheKey.density) - return false; - if (resolution != cacheKey.resolution) - return false; - if (Double.compare(cacheKey.verticalExaggeration, verticalExaggeration) != 0) - return false; - //noinspection RedundantIfStatement - if (sector != null ? !sector.equals(cacheKey.sector) : cacheKey.sector != null) - return false; - - return true; - } - - public int hashCode() - { - int result; - long temp; - result = (sector != null ? sector.hashCode() : 0); - result = 31 * result + resolution; - temp = verticalExaggeration != +0.0d ? Double.doubleToLongBits(verticalExaggeration) : 0L; - result = 31 * result + (int) (temp ^ (temp >>> 32)); - result = 31 * result + density; - return result; - } - } - - private static class RectTile implements SectorGeometry - { - private static final HashMap parameterizations = new HashMap(); - private static final HashMap indexLists = new HashMap(); - - private final Globe globe; - private final int level; - private final Sector sector; - private final Cylinder extent; // extent of triangle in object coordinates - private final int density; - private final double log10CellSize; - private long byteSize; - private RenderInfo ri; - - private PickSupport pickSupport = new PickSupport(); - private int minColorCode = 0; - private int maxColorCode = 0; - - public RectTile(Globe globe, int level, int density, Sector sector) - { - this.globe = globe; - this.level = level; - this.density = density; - this.sector = sector; - this.extent = Sector.computeBoundingCylinder(globe, 1d, this.getSector()); - double cellSize = (sector.getDeltaLatRadians() * globe.getRadius()) / density; - this.log10CellSize = Math.log10(cellSize); - } - - public Sector getSector() - { - return this.sector; - } - - public Extent getExtent() - { - return this.extent; - } - - public long getSizeInBytes() - { - return this.byteSize; - } - - private RectTile[] split() - { - Sector[] sectors = this.sector.subdivide(); - - RectTile[] subTiles = new RectTile[4]; - subTiles[0] = new RectTile(this.globe, this.level + 1, this.density, sectors[0]); - subTiles[1] = new RectTile(this.globe, this.level + 1, this.density, sectors[1]); - subTiles[2] = new RectTile(this.globe, this.level + 1, this.density, sectors[2]); - subTiles[3] = new RectTile(this.globe, this.level + 1, this.density, sectors[3]); - - return subTiles; - } - - private void makeVerts(DrawContext dc) - { - int resolution = dc.getGlobe().getElevationModel().getTargetResolution(dc, this.sector, this.density); - - if (this.ri != null && this.ri.resolution >= resolution) - return; - - MemoryCache cache = WorldWind.getMemoryCache(RectTile.class.getName()); - CacheKey cacheKey = new CacheKey(this, resolution, dc.getVerticalExaggeration(), this.density); - this.ri = (RenderInfo) cache.getObject(cacheKey); - if (this.ri != null) - return; - - this.ri = this.buildVerts(dc, this.density, resolution, true); - if (this.ri != null && this.ri.resolution >= 0) - { - cacheKey = new CacheKey(this, this.ri.resolution, dc.getVerticalExaggeration(), this.density); - cache.add(cacheKey, this.ri, this.byteSize = this.ri.getSizeInBytes()); - } - } - - private RenderInfo buildVerts(DrawContext dc, int density, int resolution, boolean makeSkirts) - { - int numVertices = (density + 3) * (density + 3); - java.nio.DoubleBuffer verts = BufferUtil.newDoubleBuffer(numVertices * 3); - - Globe globe = dc.getGlobe(); - ElevationModel.Elevations elevations = globe.getElevationModel().getElevations(this.sector, resolution); - - double latMin = this.sector.getMinLatitude().radians; - double latMax = this.sector.getMaxLatitude().radians; - double dLat = (latMax - latMin) / density; - - double lonMin = this.sector.getMinLongitude().radians; - double lonMax = this.sector.getMaxLongitude().radians; - double dLon = (lonMax - lonMin) / density; - - int iv = 0; - double lat = latMin; - double verticalExaggeration = dc.getVerticalExaggeration(); - double exaggeratedMinElevation = makeSkirts ? globe.getMinElevation() * verticalExaggeration : 0; - double equatorialRadius = globe.getEquatorialRadius(); - double eccentricity = globe.getEccentricitySquared(); - - LatLon centroid = this.sector.getCentroid(); - Vec4 refCenter = globe.computePointFromPosition(centroid.getLatitude(), centroid.getLongitude(), 0d); - - for (int j = 0; j <= density + 2; j++) - { - double cosLat = Math.cos(lat); - double sinLat = Math.sin(lat); - double rpm = equatorialRadius / Math.sqrt(1.0 - eccentricity * sinLat * sinLat); - double lon = lonMin; - for (int i = 0; i <= density + 2; i++) - { - double elevation = verticalExaggeration * elevations.getElevation(lat, lon); - if (j == 0 || j >= density + 2 || i == 0 || i >= density + 2) - { // use abs to account for negative elevation. - elevation -= exaggeratedMinElevation >= 0 ? exaggeratedMinElevation : -exaggeratedMinElevation; - } - - double x = ((rpm + elevation) * cosLat * Math.sin(lon)) - refCenter.x; - double y = ((rpm * (1.0 - eccentricity) + elevation) * sinLat) - refCenter.y; - double z = ((rpm + elevation) * cosLat * Math.cos(lon)) - refCenter.z; - - verts.put(iv++, x).put(iv++, y).put(iv++, z); - - if (i > density) - lon = lonMax; - else if (i != 0) - lon += dLon; - } - if (j > density) - lat = latMax; - else if (j != 0) - lat += dLat; - } - - return new RenderInfo(density, verts, getGeographicTextureCoordinates(density), refCenter, - elevations.getResolution()); - } - - public void renderMultiTexture(DrawContext dc, int numTextureUnits) - { - if (dc == null) - { - String msg = Logging.getMessage("nullValue.DrawContextIsNull"); - Logging.logger().severe(msg); - throw new IllegalArgumentException(msg); - } - - if (numTextureUnits < 1) - { - String msg = Logging.getMessage("generic.NumTextureUnitsLessThanOne"); - Logging.logger().severe(msg); - throw new IllegalArgumentException(msg); - } - - this.render(dc, numTextureUnits); - } - - public void render(DrawContext dc) - { - if (dc == null) - { - String msg = Logging.getMessage("nullValue.DrawContextIsNull"); - Logging.logger().severe(msg); - throw new IllegalArgumentException(msg); - } - - this.render(dc, 1); - } - - private long render(DrawContext dc, int numTextureUnits) - { - if (this.ri == null) - { - String msg = Logging.getMessage("nullValue.RenderInfoIsNull"); - Logging.logger().severe(msg); - throw new IllegalStateException(msg); - } - - dc.getView().pushReferenceCenter(dc, ri.referenceCenter); - - GL gl = dc.getGL(); - gl.glPushClientAttrib(GL.GL_CLIENT_VERTEX_ARRAY_BIT); - gl.glEnableClientState(GL.GL_VERTEX_ARRAY); - gl.glVertexPointer(3, GL.GL_DOUBLE, 0, this.ri.vertices.rewind()); - - for (int i = 0; i < numTextureUnits; i++) - { - gl.glClientActiveTexture(GL.GL_TEXTURE0 + i); - gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY); - gl.glTexCoordPointer(2, GL.GL_DOUBLE, 0, ri.texCoords.rewind()); - } - - gl.glDrawElements(javax.media.opengl.GL.GL_TRIANGLE_STRIP, this.ri.indices.limit(), - javax.media.opengl.GL.GL_UNSIGNED_INT, this.ri.indices.rewind()); - - gl.glPopClientAttrib(); - - dc.getView().popReferenceCenter(dc); - - return this.ri.indices.limit() - 2; // return number of triangles rendered - } - - public void renderWireframe(DrawContext dc, boolean showTriangles, boolean showTileBoundary) - { - if (dc == null) - { - String msg = Logging.getMessage("nullValue.DrawContextIsNull"); - Logging.logger().severe(msg); - throw new IllegalArgumentException(msg); - } - - if (this.ri == null) - { - String msg = Logging.getMessage("nullValue.RenderInfoIsNull"); - Logging.logger().severe(msg); - throw new IllegalStateException(msg); - } - - java.nio.IntBuffer indices = getIndices(this.ri.density); - indices.rewind(); - - dc.getView().pushReferenceCenter(dc, this.ri.referenceCenter); - - javax.media.opengl.GL gl = dc.getGL(); - gl.glPushAttrib( - GL.GL_DEPTH_BUFFER_BIT | GL.GL_POLYGON_BIT | GL.GL_TEXTURE_BIT | GL.GL_ENABLE_BIT | GL.GL_CURRENT_BIT); - gl.glEnable(GL.GL_BLEND); - gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE); - gl.glDisable(javax.media.opengl.GL.GL_DEPTH_TEST); - gl.glEnable(javax.media.opengl.GL.GL_CULL_FACE); - gl.glCullFace(javax.media.opengl.GL.GL_BACK); - gl.glDisable(javax.media.opengl.GL.GL_TEXTURE_2D); - gl.glColor4d(1d, 1d, 1d, 0.2); - gl.glPolygonMode(javax.media.opengl.GL.GL_FRONT, javax.media.opengl.GL.GL_LINE); - - if (showTriangles) - { - gl.glPushClientAttrib(GL.GL_CLIENT_VERTEX_ARRAY_BIT); - gl.glEnableClientState(GL.GL_VERTEX_ARRAY); - - gl.glVertexPointer(3, GL.GL_DOUBLE, 0, this.ri.vertices); - gl.glDrawElements(javax.media.opengl.GL.GL_TRIANGLE_STRIP, indices.limit(), - javax.media.opengl.GL.GL_UNSIGNED_INT, indices); - - gl.glPopClientAttrib(); - } - - dc.getView().popReferenceCenter(dc); - - if (showTileBoundary) - this.renderPatchBoundary(dc, gl); - - gl.glPopAttrib(); - } - - private void renderPatchBoundary(DrawContext dc, GL gl) - { - // TODO: Currently only works if called from renderWireframe because no state is set here. - // TODO: Draw the boundary using the vertices along the boundary rather than just at the corners. - gl.glColor4d(1d, 0, 0, 1d); - Vec4[] corners = this.sector.computeCornerPoints(dc.getGlobe()); - - gl.glBegin(javax.media.opengl.GL.GL_QUADS); - gl.glVertex3d(corners[0].x, corners[0].y, corners[0].z); - gl.glVertex3d(corners[1].x, corners[1].y, corners[1].z); - gl.glVertex3d(corners[2].x, corners[2].y, corners[2].z); - gl.glVertex3d(corners[3].x, corners[3].y, corners[3].z); - gl.glEnd(); - } - - public void renderBoundingVolume(DrawContext dc) - { - ((Cylinder) this.getExtent()).render(dc); - } - - public void pick(DrawContext dc, java.awt.Point pickPoint) - { - if (this.ri == null) - return; - - renderTrianglesWithUniqueColors(dc, ri); - - int colorCode = pickSupport.getTopColor(dc, pickPoint); - if (colorCode < minColorCode || colorCode > maxColorCode) - return; - - double EPSILON = (double) 0.00001f; - - int triangleIndex = colorCode - minColorCode - 1; - - if ((null != ri.indices) && (triangleIndex < ri.indices.capacity() - 2)) - { - double centerX = ri.referenceCenter.x; - double centerY = ri.referenceCenter.y; - double centerZ = ri.referenceCenter.z; - - int vIndex = 3 * ri.indices.get(triangleIndex); - Vec4 v0 = new Vec4((ri.vertices.get(vIndex++) + centerX), - (ri.vertices.get(vIndex++) + centerY), - (ri.vertices.get(vIndex) + centerZ)); - - vIndex = 3 * ri.indices.get(triangleIndex + 1); - Vec4 v1 = new Vec4((ri.vertices.get(vIndex++) + centerX), - (ri.vertices.get(vIndex++) + centerY), - (ri.vertices.get(vIndex) + centerZ)); - - vIndex = 3 * ri.indices.get(triangleIndex + 2); - Vec4 v2 = new Vec4((ri.vertices.get(vIndex++) + centerX), - (ri.vertices.get(vIndex++) + centerY), - (ri.vertices.get(vIndex) + centerZ)); - - // get triangle edge vectors and plane normal - Vec4 e1 = v1.subtract3(v0); - Vec4 e2 = v2.subtract3(v0); - Vec4 N = e1.cross3(e2); // if N is 0, the triangle is degenerate, we are not dealing with it - - Line ray = dc.getView().computeRayFromScreenPoint(pickPoint.getX(), pickPoint.getY()); - - Vec4 w0 = ray.getOrigin().subtract3(v0); - double a = -N.dot3(w0); - double b = N.dot3(ray.getDirection()); - if (java.lang.Math.abs(b) < EPSILON) // ray is parallel to triangle plane - return; // if a == 0 , ray lies in triangle plane - double r = a / b; - - Vec4 intersect = ray.getOrigin().add3(ray.getDirection().multiply3(r)); - Position pp = dc.getGlobe().computePositionFromPoint(intersect); - - // Draw the elevation from the elevation model, not the geode. - double elev = dc.getGlobe().getElevation(pp.getLatitude(), pp.getLongitude()); - Position p = new Position(pp.getLatitude(), pp.getLongitude(), elev); - - PickedObject po = new PickedObject(colorCode, p, pp.getLatitude(), pp.getLongitude(), elev, true); - dc.addPickedObject(po); - } - } - - private void renderTrianglesWithUniqueColors(DrawContext dc, RenderInfo ri) - { - if (dc == null) - { - String message = Logging.getMessage("nullValue.DrawContextIsNull"); - Logging.logger().severe(message); - throw new IllegalStateException(message); - } - - if (ri.vertices == null) - return; - - ri.vertices.rewind(); - ri.indices.rewind(); - - javax.media.opengl.GL gl = dc.getGL(); - - if (null != ri.referenceCenter) - dc.getView().pushReferenceCenter(dc, ri.referenceCenter); - - minColorCode = dc.getUniquePickColor().getRGB(); - int trianglesNum = ri.indices.capacity() - 2; - - gl.glBegin(GL.GL_TRIANGLES); - for (int i = 0; i < trianglesNum; i++) - { - java.awt.Color color = dc.getUniquePickColor(); - gl.glColor3ub((byte) (color.getRed() & 0xFF), - (byte) (color.getGreen() & 0xFF), - (byte) (color.getBlue() & 0xFF)); - - int vIndex = 3 * ri.indices.get(i); - gl.glVertex3d(ri.vertices.get(vIndex), ri.vertices.get(vIndex + 1), ri.vertices.get( - vIndex + 2)); - - vIndex = 3 * ri.indices.get(i + 1); - gl.glVertex3d(ri.vertices.get(vIndex), ri.vertices.get(vIndex + 1), ri.vertices.get( - vIndex + 2)); - - vIndex = 3 * ri.indices.get(i + 2); - gl.glVertex3d(ri.vertices.get(vIndex), ri.vertices.get(vIndex + 1), ri.vertices.get( - vIndex + 2)); - } - gl.glEnd(); - maxColorCode = dc.getUniquePickColor().getRGB(); - - if (null != ri.referenceCenter) - dc.getView().popReferenceCenter(dc); - } - - public Vec4 getSurfacePoint(Angle latitude, Angle longitude, double metersOffset) - { - if (latitude == null || longitude == null) - { - String msg = Logging.getMessage("nullValue.LatLonIsNull"); - Logging.logger().severe(msg); - throw new IllegalArgumentException(msg); - } - - if (!this.sector.contains(latitude, longitude)) - { - // not on this geometry - return null; - } - - if (this.ri == null) - return null; - - double lat = latitude.getDegrees(); - double lon = longitude.getDegrees(); - - double bottom = this.sector.getMinLatitude().getDegrees(); - double top = this.sector.getMaxLatitude().getDegrees(); - double left = this.sector.getMinLongitude().getDegrees(); - double right = this.sector.getMaxLongitude().getDegrees(); - - double leftDecimal = (lon - left) / (right - left); - double bottomDecimal = (lat - bottom) / (top - bottom); - - int row = (int) (bottomDecimal * (this.density)); - int column = (int) (leftDecimal * (this.density)); - - double l = createPosition(column, leftDecimal, ri.density); - double h = createPosition(row, bottomDecimal, ri.density); - - Vec4 result = RectTile.interpolate(row, column, l, h, ri); - result = result.add3(ri.referenceCenter); - if (metersOffset != 0) - result = applyOffset(this.globe, result, metersOffset); - - return result; - } - - /** - * Offsets point by metersOffset meters. - * - * @param globe the Globe from which to offset - * @param point the Vec4 to offset - * @param metersOffset the magnitude of the offset - * @return point offset along its surface normal as if it were on globe - */ - private static Vec4 applyOffset(Globe globe, Vec4 point, double metersOffset) - { - Vec4 normal = globe.computeSurfaceNormalAtPoint(point); - point = Vec4.fromLine3(point, metersOffset, normal); - return point; - } - - /** - * Computes from a column (or row) number, and a given offset ranged [0,1] corresponding to the distance along - * the edge of this sector, where between this column and the next column the corresponding position will fall, - * in the range [0,1]. - * - * @param start the number of the column or row to the left, below or on this position - * @param decimal the distance from the left or bottom of the current sector that this position falls - * @param density the number of intervals along the sector's side - * @return a decimal ranged [0,1] representing the position between two columns or rows, rather than between two - * edges of the sector - */ - private static double createPosition(int start, double decimal, int density) - { - double l = ((double) start) / (double) density; - double r = ((double) (start + 1)) / (double) density; - - return (decimal - l) / (r - l); - } - - /** - * Calculates a Point that sits at xDec offset from column to - * column + 1 and at yDec offset from row to row + 1. - * Accounts for the diagonals. - * - * @param row represents the row which corresponds to a yDec value of 0 - * @param column represents the column which corresponds to an xDec value of 0 - * @param xDec constrained to [0,1] - * @param yDec constrained to [0,1] - * @param ri the render info holding the vertices, etc. - * @return a Point geometrically within or on the boundary of the quadrilateral whose bottom left - * corner is indexed by (row, column) - */ - private static Vec4 interpolate(int row, int column, double xDec, double yDec, RenderInfo ri) - { - row++; - column++; - - int numVerticesPerEdge = ri.density + 3; - - int bottomLeft = row * numVerticesPerEdge + column; - - bottomLeft *= 3; - - int numVertsTimesThree = numVerticesPerEdge * 3; - - Vec4 bL = new Vec4(ri.vertices.get(bottomLeft), ri.vertices.get(bottomLeft + 1), ri.vertices.get( - bottomLeft + 2)); - Vec4 bR = new Vec4(ri.vertices.get(bottomLeft + 3), ri.vertices.get(bottomLeft + 4), - ri.vertices.get(bottomLeft + 5)); - - bottomLeft += numVertsTimesThree; - - Vec4 tL = new Vec4(ri.vertices.get(bottomLeft), ri.vertices.get(bottomLeft + 1), ri.vertices.get( - bottomLeft + 2)); - Vec4 tR = new Vec4(ri.vertices.get(bottomLeft + 3), ri.vertices.get(bottomLeft + 4), - ri.vertices.get(bottomLeft + 5)); - - return interpolate(bL, bR, tR, tL, xDec, yDec); - } - - /** - * Calculates the point at (xDec, yDec) in the two triangles defined by {bL, bR, tL} and {bR, tR, tL}. If - * thought of as a quadrilateral, the diagonal runs from tL to bR. Of course, this isn't a quad, it's two - * triangles. - * - * @param bL the bottom left corner - * @param bR the bottom right corner - * @param tR the top right corner - * @param tL the top left corner - * @param xDec how far along, [0,1] 0 = left edge, 1 = right edge - * @param yDec how far along, [0,1] 0 = bottom edge, 1 = top edge - * @return the point xDec, yDec in the co-ordinate system defined by bL, bR, tR, tL - */ - private static Vec4 interpolate(Vec4 bL, Vec4 bR, Vec4 tR, Vec4 tL, double xDec, double yDec) - { - double pos = xDec + yDec; - if (pos == 1) - { - // on the diagonal - what's more, we don't need to do any "oneMinusT" calculation - return new Vec4( - tL.x * yDec + bR.x * xDec, - tL.y * yDec + bR.y * xDec, - tL.z * yDec + bR.z * xDec); - } - else if (pos > 1) - { - // in the "top right" half - - // vectors pointing from top right towards the point we want (can be thought of as "negative" vectors) - Vec4 horizontalVector = (tL.subtract3(tR)).multiply3(1 - xDec); - Vec4 verticalVector = (bR.subtract3(tR)).multiply3(1 - yDec); - - return tR.add3(horizontalVector).add3(verticalVector); - } - else - { - // pos < 1 - in the "bottom left" half - - // vectors pointing from the bottom left towards the point we want - Vec4 horizontalVector = (bR.subtract3(bL)).multiply3(xDec); - Vec4 verticalVector = (tL.subtract3(bL)).multiply3(yDec); - - return bL.add3(horizontalVector).add3(verticalVector); - } - } - - public String toString() - { - return "level " + this.level + ", density " + this.density + ", sector " + this.sector; - } - - protected static java.nio.DoubleBuffer getGeographicTextureCoordinates(int density) - { - if (density < 1) - { - density = 1; - } - - // Approximate 1 to avoid shearing off of right and top skirts in SurfaceTileRenderer. - // TODO: dig into this more: why are the skirts being sheared off? - final double one = 0.999999; - - java.nio.DoubleBuffer p = parameterizations.get(density); - if (p != null) - return p; - - int coordCount = (density + 3) * (density + 3); - p = com.sun.opengl.util.BufferUtil.newDoubleBuffer(2 * coordCount); - double delta = 1d / density; - int k = 2 * (density + 3); - for (int j = 0; j < density; j++) - { - double v = j * delta; - - // skirt column; duplicate first column - p.put(k++, 0d); - p.put(k++, v); - - // interior columns - for (int i = 0; i < density; i++) - { - p.put(k++, i * delta); // u - p.put(k++, v); - } - - // last interior column; force u to 1. - p.put(k++, one);//1d); - p.put(k++, v); - - // skirt column; duplicate previous column - p.put(k++, one);//1d); - p.put(k++, v); - } - - // Last interior row - //noinspection UnnecessaryLocalVariable - double v = one;//1d; - p.put(k++, 0d); // skirt column - p.put(k++, v); - - for (int i = 0; i < density; i++) - { - p.put(k++, i * delta); // u - p.put(k++, v); - } - p.put(k++, one);//1d); // last interior column - p.put(k++, v); - - p.put(k++, one);//1d); // skirt column - p.put(k++, v); - - // last skirt row - int kk = k - 2 * (density + 3); - for (int i = 0; i < density + 3; i++) - { - p.put(k++, p.get(kk++)); - p.put(k++, p.get(kk++)); - } - - // first skirt row - k = 0; - kk = 2 * (density + 3); - for (int i = 0; i < density + 3; i++) - { - p.put(k++, p.get(kk++)); - p.put(k++, p.get(kk++)); - } - - parameterizations.put(density, p); - - return p; - } -// -// protected static DoubleBuffer getGeometricTextureCoordinates(Sector sector, double radius, int density) -// { -// if (density < 1) -// density = 1; -// -// // Approximate 1 to avoid shearing off of right and top skirts in SurfaceTileRenderer. -// // TODO: dig into this more: why are the skirts being sheared off? -// final double one = 0.999999; -// -// DoubleBuffer p; -// int coordCount = (density + 3) * (density + 3); -// p = BufferUtil.newDoubleBuffer(2 * coordCount); -// -// LatLon sw = new LatLon(sector.getMinLatitude(), sector.getMinLongitude()); -// LatLon nw = new LatLon(sector.getMaxLatitude(), sector.getMinLongitude()); -// LatLon se = new LatLon(sector.getMinLatitude(), sector.getMaxLongitude()); -// LatLon ne = new LatLon(sector.getMaxLatitude(), sector.getMaxLongitude()); -// -// double swse = SphericalGeometry.unitDistance(sw, se); -// double nwne = SphericalGeometry.unitDistance(nw, ne); -// double swnw = SphericalGeometry.unitDistance(sw, nw); -// double sene = SphericalGeometry.unitDistance(se, ne); -// double s3 = 0.5 * (swse - nwne) / swse; -// double s4 = s3 + nwne / swse; -// -// double dt = 1d / density; -// int k = 2 * (density + 3); -// for (int j = 0; j < density; j++) -// { -// double t = j * dt; -// double s3p = t * s3; -// double s4p = 1 - s3p;//1 + t * (s4 - 1); -// double ds = (s4p - s3p) / density; -// double s = s3p; -// -// // skirt column; duplicate first column -// p.put(k++, s); -// p.put(k++, t); -// -// // interior columns -// for (int i = 0; i <= density; i++) -// { -// p.put(k++, s + i * ds); // u -// p.put(k++, t); -// } -// -// // skirt column; duplicate previous column -// p.put(k++, s + ds * density); -// p.put(k++, t); -// } -// -// // Last interior row -// //noinspection UnnecessaryLocalVariable -// double t = one; -// double ds = (s4 - s3) / density; -// //noinspection UnnecessaryLocalVariable -// double s = s3; -// -// p.put(k++, s); // skirt column -// p.put(k++, t); -// -// for (int i = 0; i <= density; i++) -// { -// p.put(k++, s + i * ds); // u -// p.put(k++, t); -// } -// -// p.put(k++, s + ds * density);//1d); // skirt column -// p.put(k++, t); -// -// // last skirt row -// int kk = k - 2 * (density + 3); -// for (int i = 0; i < density + 3; i++) -// { -// p.put(k++, p.get(kk++)); -// p.put(k++, p.get(kk++)); -// } -// -// // first skirt row -// k = 0; -// kk = 2 * (density + 3); -// for (int i = 0; i < density + 3; i++) -// { -// p.put(k++, p.get(kk++)); -// p.put(k++, p.get(kk++)); -// } -// -// return p; -// } - - private static java.nio.IntBuffer getIndices(int density) - { - if (density < 1) - density = 1; - - // return a pre-computed buffer if possible. - java.nio.IntBuffer buffer = indexLists.get(density); - if (buffer != null) - return buffer; - - int sideSize = density + 2; - - int indexCount = 2 * sideSize * sideSize + 4 * sideSize - 2; - buffer = com.sun.opengl.util.BufferUtil.newIntBuffer(indexCount); - int k = 0; - for (int i = 0; i < sideSize; i++) - { - buffer.put(k); - if (i > 0) - { - buffer.put(++k); - buffer.put(k); - } - - if (i % 2 == 0) // even - { - buffer.put(++k); - for (int j = 0; j < sideSize; j++) - { - k += sideSize; - buffer.put(k); - buffer.put(++k); - } - } - else // odd - { - buffer.put(--k); - for (int j = 0; j < sideSize; j++) - { - k -= sideSize; - buffer.put(k); - buffer.put(--k); - } - } - } - - indexLists.put(density, buffer); - - return buffer; - } - } - - private java.util.ArrayList topLevels; - private SectorGeometryList currentTiles = new SectorGeometryList(); - private Frustum currentFrustum; - private int currentLevel; - private int maxLevel = DEFAULT_MAX_LEVEL;//14; // TODO: Make configurable - private Sector sector; // union of all tiles selected during call to render() - private int density = DEFAULT_DENSITY; // TODO: make configurable - - public EllipsoidRectangularTessellator() - { -// this.topLevels = createTopLevelTiles(globe, DEFAULT_NUM_LAT_SUBDIVISIONS, DEFAULT_NUM_LON_SUBDIVISIONS); - } - - public void setGlobe(Globe globe) - { - if (globe == null) - { - String msg = Logging.getMessage("nullValue.GlobeIsNull"); - Logging.logger().severe(msg); - throw new IllegalArgumentException(msg); - } - - this.topLevels = createTopLevelTiles(globe, DEFAULT_NUM_LAT_SUBDIVISIONS, DEFAULT_NUM_LON_SUBDIVISIONS); - } - - public Sector getSector() - { - return this.sector; - } - - private ArrayList createTopLevelTiles(Globe globe, int nRows, int nCols) - { - ArrayList tops = new ArrayList(nRows * nCols); - - double deltaLat = 180d / nRows; - double deltaLon = 360d / nCols; - Angle lastLat = Angle.NEG90; - - for (int row = 0; row < DEFAULT_NUM_LAT_SUBDIVISIONS; row++) - { - Angle lat = lastLat.addDegrees(deltaLat); - if (lat.getDegrees() + 1d > 90d) - lat = Angle.POS90; - - Angle lastLon = Angle.NEG180; - - for (int col = 0; col < DEFAULT_NUM_LON_SUBDIVISIONS; col++) - { - Angle lon = lastLon.addDegrees(deltaLon); - if (lon.getDegrees() + 1d > 180d) - lon = Angle.POS180; - - tops.add(new RectTile(globe, 0, this.density, new Sector(lastLat, lat, lastLon, lon))); - lastLon = lon; - } - lastLat = lat; - } - - return tops; - } - - public SectorGeometryList tessellate(DrawContext dc) - { - if (dc == null) - { - String msg = Logging.getMessage("nullValue.DrawContextIsNull"); - Logging.logger().severe(msg); - throw new IllegalArgumentException(msg); - } - - if (dc.getView() == null) - { - String msg = Logging.getMessage("nullValue.ViewIsNull"); - Logging.logger().severe(msg); - throw new IllegalStateException(msg); - } - - String cacheName = RectTile.class.getName(); - if (!WorldWind.getMemoryCacheSet().containsCache(cacheName)) - { - long size = Configuration.getLongValue(AVKey.SECTOR_GEOMETRY_CACHE_SIZE, 20000000L); - MemoryCache cache = new BasicMemoryCache((long) (0.85 * size), size); - cache.setName("Terrain"); - WorldWind.getMemoryCacheSet().addCache(cacheName, cache); - } - - this.currentTiles.clear(); - this.currentLevel = 0; - this.sector = null; - - this.currentFrustum = dc.getView().getFrustumInModelCoordinates(); - for (RectTile tile : topLevels) - { - this.selectVisibleTiles(dc, tile); - } - - dc.setVisibleSector(this.getSector()); - - for (SectorGeometry tile : this.currentTiles) - { - ((RectTile) tile).makeVerts(dc); - } - - return this.currentTiles; - } - - private void selectVisibleTiles(DrawContext dc, RectTile tile) - { - if (!tile.getExtent().intersects(this.currentFrustum)) - return; - - if (this.currentLevel < this.maxLevel && needToSplit(dc, tile)) - { - ++this.currentLevel; - RectTile[] subtiles = tile.split(); - for (RectTile child : subtiles) - { - this.selectVisibleTiles(dc, child); - } - --this.currentLevel; - return; - } - this.sector = tile.getSector().union(this.sector); - this.currentTiles.add(tile); - } - - private static boolean needToSplit(DrawContext dc, RectTile tile) - { - Vec4[] corners = tile.sector.computeCornerPoints(dc.getGlobe()); - Vec4 centerPoint = tile.sector.computeCenterPoint(dc.getGlobe()); - - View view = dc.getView(); - double d1 = view.getEyePoint().distanceTo3(corners[0]); - double d2 = view.getEyePoint().distanceTo3(corners[1]); - double d3 = view.getEyePoint().distanceTo3(corners[2]); - double d4 = view.getEyePoint().distanceTo3(corners[3]); - double d5 = view.getEyePoint().distanceTo3(centerPoint); - - double minDistance = d1; - if (d2 < minDistance) - minDistance = d2; - if (d3 < minDistance) - minDistance = d3; - if (d4 < minDistance) - minDistance = d4; - if (d5 < minDistance) - minDistance = d5; - - double logDist = Math.log10(minDistance); - boolean useTile = tile.log10CellSize <= (logDist - DEFAULT_LOG10_RESOLUTION_TARGET); - - return !useTile; - } -// -// private static void printTextureCoords(DoubleBuffer tcs, int density) -// { -// tcs.rewind(); -// for (int j = density + 2; j >= 0; j--) -// { -// System.out.printf("%2d: ", j * (density + 3)); -// for (int i = 0; i <= 2 * (density + 2); i += 2) -// { -// System.out.printf("(%6.3f, %6.3f) ", -// tcs.get(2 * j * (density + 3) + i), tcs.get(2 * j * (density + 3) + i + 1)); -// } -// System.out.println(); -// } -// } -} diff --git a/gov/nasa/worldwind/util/BasicNetworkStatus.java b/gov/nasa/worldwind/util/BasicNetworkStatus.java index 567fdff..7374490 100644 --- a/gov/nasa/worldwind/util/BasicNetworkStatus.java +++ b/gov/nasa/worldwind/util/BasicNetworkStatus.java @@ -6,10 +6,12 @@ All Rights Reserved. */ package gov.nasa.worldwind.util; -import gov.nasa.worldwind.avlist.AVListImpl; +import gov.nasa.worldwind.avlist.*; +import gov.nasa.worldwind.Configuration; import java.net.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.*; import java.io.IOException; /** @@ -30,52 +32,81 @@ import java.io.IOException; * servers cab be reached. * * @author tag - * @version $Id: BasicNetworkStatus.java 3558 2007-11-17 08:36:45Z tgaskins $ + * @version $Id: BasicNetworkStatus.java 3735 2007-12-06 02:20:43Z tgaskins $ */ public class BasicNetworkStatus extends AVListImpl implements NetworkStatus { - private static final long DEFAULT_TRY_AGAIN_INTERVAL = (long) 120e3; // seconds + private static final long DEFAULT_TRY_AGAIN_INTERVAL = (long) 12e3; // seconds private static final int DEFAULT_ATTEMPT_LIMIT = 10; // number of unavailable events to declare host unavailable private static final String[] networkTestSites = new String[] - {"www.nasa.gov", "worldwind.arc.nasa.gov", "google.com", "microsoft.com"}; + {"www.nasa.gov", "worldwind.arc.nasa.gov", "google.com", "microsoft.com", "yahoo.com"}; private static final long NETWORK_STATUS_REPORT_INTERVAL = (long) 60e3; private static class HostInfo { private final long tryAgainInterval; private final int attemptLimit; - private int logCount; - private long lastLogTime; + private AtomicInteger logCount = new AtomicInteger(); + private AtomicLong lastLogTime = new AtomicLong(); private HostInfo(int attemptLimit, long tryAgainInterval) { - this.lastLogTime = System.currentTimeMillis(); - this.logCount = 1; + this.lastLogTime.set(System.currentTimeMillis()); + this.logCount.set(1); this.tryAgainInterval = tryAgainInterval; this.attemptLimit = attemptLimit; } private boolean isUnavailable() { - return this.logCount >= this.attemptLimit; + return this.logCount.get() >= this.attemptLimit; } private boolean isTimeToTryAgain() { - return System.currentTimeMillis() - this.lastLogTime >= this.tryAgainInterval; + return System.currentTimeMillis() - this.lastLogTime.get() >= this.tryAgainInterval; } } - private long tryAgainInterval = DEFAULT_TRY_AGAIN_INTERVAL; - private int attemptLimit = DEFAULT_ATTEMPT_LIMIT; private ConcurrentHashMap hostMap = new ConcurrentHashMap(); + private AtomicLong tryAgainInterval = new AtomicLong(DEFAULT_TRY_AGAIN_INTERVAL); + private AtomicInteger attemptLimit = new AtomicInteger(DEFAULT_ATTEMPT_LIMIT); + // Fields for determining overall network status. - private long lastUnavailableLogTime = System.currentTimeMillis(); - private long lastAvailableLogTime = System.currentTimeMillis() + 1; - private long lastNetworkCheckTime = System.currentTimeMillis(); - private long lastNetworkStatusReportTime = 0; - private boolean lastNetworkUnavailableResult = false; + private boolean offlineMode; + private AtomicLong lastUnavailableLogTime = new AtomicLong(System.currentTimeMillis()); + private AtomicLong lastAvailableLogTime = new AtomicLong(System.currentTimeMillis() + 1); + private AtomicLong lastNetworkCheckTime = new AtomicLong(System.currentTimeMillis()); + private AtomicLong lastNetworkStatusReportTime = new AtomicLong(0); + private AtomicBoolean lastNetworkUnavailableResult = new AtomicBoolean(false); + + public BasicNetworkStatus() + { + String oms = Configuration.getStringValue(AVKey.OFFLINE_MODE, "false"); + this.offlineMode = oms.startsWith("t") || oms.startsWith("T"); + } + + /** + * Indicates whether World Wind will attempt to connect to the network to retrieve data or for other reasons. + * + * @return true if World Wind is in off-line mode, false if not. + */ + public boolean isOfflineMode() + { + return offlineMode; + } + + /** + * Indicate whether World Wind should attempt to connect to the network to retrieve data or for other reasons. + * The default value for this attribute is false, indicating that the network should be used. + * + * @param offlineMode true if World Wind should use the network, false otherwise + */ + public void setOfflineMode(boolean offlineMode) + { + this.offlineMode = offlineMode; + } /** * Set the number of times a host must be logged as unavailable before it is marked unavailable in this class. @@ -83,7 +114,7 @@ public class BasicNetworkStatus extends AVListImpl implements NetworkStatus * @param limit the number of log-unavailability invocations necessary to consider the host unreachable. * @throws IllegalArgumentException if the limit is less than 1. */ - public synchronized void setAttemptLimit(int limit) + public void setAttemptLimit(int limit) { if (limit < 1) { @@ -92,7 +123,7 @@ public class BasicNetworkStatus extends AVListImpl implements NetworkStatus throw new IllegalArgumentException(message); } - this.attemptLimit = limit; + this.attemptLimit.set(limit); } /** @@ -102,7 +133,7 @@ public class BasicNetworkStatus extends AVListImpl implements NetworkStatus * @param interval The length of time, in milliseconds, to wait to unmark a host as unreachable. * @throws IllegalArgumentException if the interval is less than 0. */ - public synchronized void setTryAgainInterval(long interval) + public void setTryAgainInterval(long interval) { if (interval < 0) { @@ -111,7 +142,7 @@ public class BasicNetworkStatus extends AVListImpl implements NetworkStatus throw new IllegalArgumentException(message); } - this.tryAgainInterval = interval; + this.tryAgainInterval.set(interval); } /** @@ -119,9 +150,9 @@ public class BasicNetworkStatus extends AVListImpl implements NetworkStatus * * @return the limit. */ - public synchronized int getAttemptLimit() + public int getAttemptLimit() { - return this.attemptLimit; + return this.attemptLimit.get(); } /** @@ -130,9 +161,9 @@ public class BasicNetworkStatus extends AVListImpl implements NetworkStatus * * @return the interval, in milliseconds. */ - public synchronized long getTryAgainInterval() + public long getTryAgainInterval() { - return this.tryAgainInterval; + return this.tryAgainInterval.get(); } /** @@ -141,8 +172,11 @@ public class BasicNetworkStatus extends AVListImpl implements NetworkStatus * * @param url a url containing the host to mark as unavailable. */ - public synchronized void logUnavailableHost(URL url) + public void logUnavailableHost(URL url) { + if (this.offlineMode) + return; + if (url == null) { String message = Logging.getMessage("nullValue.URLIsNull"); @@ -155,16 +189,16 @@ public class BasicNetworkStatus extends AVListImpl implements NetworkStatus { HostInfo hi = this.hostMap.get(hostName); if (!hi.isUnavailable()) - ++hi.logCount; - hi.lastLogTime = System.currentTimeMillis(); + hi.logCount.incrementAndGet(); + hi.lastLogTime.set(System.currentTimeMillis()); } else { - HostInfo hi = new HostInfo(this.attemptLimit, this.tryAgainInterval); + HostInfo hi = new HostInfo(this.attemptLimit.get(), this.tryAgainInterval.get()); this.hostMap.put(hostName, hi); } - this.lastUnavailableLogTime = System.currentTimeMillis(); + this.lastUnavailableLogTime.set(System.currentTimeMillis()); } /** @@ -173,8 +207,11 @@ public class BasicNetworkStatus extends AVListImpl implements NetworkStatus * * @param url a url containing the host to mark as available. */ - public synchronized void logAvailableHost(URL url) + public void logAvailableHost(URL url) { + if (this.offlineMode) + return; + if (url == null) { String message = Logging.getMessage("nullValue.URLIsNull"); @@ -186,7 +223,7 @@ public class BasicNetworkStatus extends AVListImpl implements NetworkStatus if (this.hostMap.containsKey(hostName)) this.hostMap.remove(hostName); - this.lastAvailableLogTime = System.currentTimeMillis(); + this.lastAvailableLogTime.set(System.currentTimeMillis()); } /** @@ -196,8 +233,11 @@ public class BasicNetworkStatus extends AVListImpl implements NetworkStatus * @param url a url containing the host to check for availability. * @return true if the host is marked as unavailable, otherwise false. */ - public synchronized boolean isHostUnavailable(URL url) + public boolean isHostUnavailable(URL url) { + if (this.offlineMode) + return true; + if (url == null) { String message = Logging.getMessage("nullValue.URLIsNull"); @@ -224,9 +264,9 @@ public class BasicNetworkStatus extends AVListImpl implements NetworkStatus * * @return false if the network can be reached or has been reached in the previous five seconds, otherwise true. */ - public synchronized boolean isNetworkUnavailable() + public boolean isNetworkUnavailable() { - return this.isNetworkUnavailable(5000L); + return this.offlineMode || this.isNetworkUnavailable(5000L); } /** @@ -236,33 +276,38 @@ public class BasicNetworkStatus extends AVListImpl implements NetworkStatus * recently. * @return false if the network can be reached or has been reached in a specified time, otherwise true. */ - public synchronized boolean isNetworkUnavailable(long checkInterval) + public boolean isNetworkUnavailable(long checkInterval) { + if (this.offlineMode) + return true; + // If there's been success since failure, network assumed to be reachable. - if (this.lastAvailableLogTime > this.lastUnavailableLogTime) + if (this.lastAvailableLogTime.get() > this.lastUnavailableLogTime.get()) { - return this.lastNetworkUnavailableResult = false; + this.lastNetworkUnavailableResult.set(false); + return this.lastNetworkUnavailableResult.get(); } long now = System.currentTimeMillis(); // If there's been success recently, network assumed to be reachable. - if (!this.lastNetworkUnavailableResult && now - this.lastAvailableLogTime < checkInterval) + if (!this.lastNetworkUnavailableResult.get() && now - this.lastAvailableLogTime.get() < checkInterval) { - return this.lastNetworkUnavailableResult; + return this.lastNetworkUnavailableResult.get(); } // If query comes too soon after an earlier one that addressed the network, return the earlier result. - if (now - this.lastNetworkCheckTime < checkInterval) + if (now - this.lastNetworkCheckTime.get() < checkInterval) { - return this.lastNetworkUnavailableResult; + return this.lastNetworkUnavailableResult.get(); } - this.lastNetworkCheckTime = now; + this.lastNetworkCheckTime.set(now); if (!this.isWorlWindServerUnavailable()) { - return this.lastNetworkUnavailableResult = false; // network not unreachable + this.lastNetworkUnavailableResult.set(false); // network not unreachable + return this.lastNetworkUnavailableResult.get(); } for (String testHost : networkTestSites) @@ -270,19 +315,21 @@ public class BasicNetworkStatus extends AVListImpl implements NetworkStatus if (this.isHostReachable(testHost)) { { - return this.lastNetworkUnavailableResult = false; // network not unreachable + this.lastNetworkUnavailableResult.set(false); // network not unreachable + return this.lastNetworkUnavailableResult.get(); } } } - if (now - this.lastNetworkStatusReportTime > NETWORK_STATUS_REPORT_INTERVAL) + if (now - this.lastNetworkStatusReportTime.get() > NETWORK_STATUS_REPORT_INTERVAL) { - this.lastNetworkStatusReportTime = now; + this.lastNetworkStatusReportTime.set(now); String message = Logging.getMessage("NetworkStatus.NetworkUnreachable"); Logging.logger().info(message); } - return this.lastNetworkUnavailableResult = true; // if no successful contact then network is unreachable + this.lastNetworkUnavailableResult.set(true); // if no successful contact then network is unreachable + return this.lastNetworkUnavailableResult.get(); } /** @@ -290,12 +337,12 @@ public class BasicNetworkStatus extends AVListImpl implements NetworkStatus * * @return false if the servers can be reached, otherwise true. */ - public synchronized boolean isWorlWindServerUnavailable() + public boolean isWorlWindServerUnavailable() { - return !this.isHostReachable("worldwind.arc.nasa.gov"); + return this.offlineMode || !this.isHostReachable("worldwind.arc.nasa.gov"); } - private synchronized boolean isHostReachable(String hostName) + private boolean isHostReachable(String hostName) { try { diff --git a/gov/nasa/worldwind/util/NetworkStatus.java b/gov/nasa/worldwind/util/NetworkStatus.java index d5dadac..5159379 100644 --- a/gov/nasa/worldwind/util/NetworkStatus.java +++ b/gov/nasa/worldwind/util/NetworkStatus.java @@ -12,7 +12,7 @@ import java.net.URL; /** * @author tag - * @version $Id: NetworkStatus.java 3503 2007-11-14 05:48:29Z tgaskins $ + * @version $Id: NetworkStatus.java 3735 2007-12-06 02:20:43Z tgaskins $ */ public interface NetworkStatus extends AVList { @@ -29,4 +29,36 @@ public interface NetworkStatus extends AVList int getAttemptLimit(); long getTryAgainInterval(); + + /** + * Indicates whether World Wind will attempt to connect to the network to retrieve data or for other reasons. + * + * @return true if World Wind is in off-line mode, false if not. + */ + boolean isOfflineMode(); + + /** + * Indicate whether World Wind should attempt to connect to the network to retrieve data or for other reasons. + * The default value for this attribute is false, indicating that the network should be used. + * + * @param offlineMode true if World Wind should use the network, false otherwise + */ + void setOfflineMode(boolean offlineMode); + + /** + * Set the number of times a host must be logged as unavailable before it is marked unavailable in this class. + * + * @param limit the number of log-unavailability invocations necessary to consider the host unreachable. + * @throws IllegalArgumentException if the limit is less than 1. + */ + void setAttemptLimit(int limit); + + /** + * Set the length of time to wait until a host is marked as not unreachable subsequent to its being marked + * unreachable. + * + * @param interval The length of time, in milliseconds, to wait to unmark a host as unreachable. + * @throws IllegalArgumentException if the interval is less than 0. + */ + void setTryAgainInterval(long interval); } diff --git a/gov/nasa/worldwind/view/View.java b/gov/nasa/worldwind/view/View.java deleted file mode 100644 index da59035..0000000 --- a/gov/nasa/worldwind/view/View.java +++ /dev/null @@ -1,239 +0,0 @@ -/* -Copyright (C) 2001, 2006 United States Government as represented by -the Administrator of the National Aeronautics and Space Administration. -All Rights Reserved. -*/ -package gov.nasa.worldwind.view; - -import gov.nasa.worldwind.WWObject; -import gov.nasa.worldwind.geom.*; -import gov.nasa.worldwind.render.DrawContext; - -/** - * View provides a coordinate transformation from Model coordinates to eye coordinates, - * following the OpenGL convention of a left-handed coordinate system with the origin at the eye point and looking down - * the negative Z axis. View also provides a transformation from eye coordinates to screen coordinates, - * following the OpenGL convention of an origin in the lower left hand screen corner. - *

- * View contains both fixed state and computed state. The computed state is typically updated during a call - * to the {@link #apply} method. Most accessor methods in this interface return the computed state that was set during - * the most recent call to apply(). - * - * @author Paul Collins - * @version $Id: View.java 2491 2007-08-02 18:48:00Z dcollins $ - * @see ViewStateIterator - * @see gov.nasa.worldwind.view.OrbitView - */ -public interface View extends WWObject -{ - /** - * Calculates and applies View's internal state to the graphics context in DrawContext. - * All subsequently rendered objects use this new state. Upon return, the OpenGL graphics context reflects the - * values of this view, as do any computed values of the view, such as the model-view matrix, projection matrix and - * Frustum. - * - * @param dc the current World Wind drawing context on which View's state will apply. - * @throws IllegalArgumentException if dc is null, or if the Globe or GL - * instances in dc are null. - */ - void apply(DrawContext dc); - - /** - * Maps a Point in model (cartesian) coordinates to a Point in screen coordinates. The - * returned x and y are relative to the lower left hand screen corner, while z is the screen depth-coordinate. If - * the model point cannot be sucessfully mapped, this will return null. - * - * @param modelPoint the model coordinate Point to project. - * @return the mapped screen coordinate Point. - * @throws IllegalArgumentException if modelPoint is null. - */ - Vec4 project(Vec4 modelPoint); - - /** - * Maps a Point in screen coordinates to a Point in model coordinates. The input x and y - * are relative to the lower left hand screen corner, while z is the screen depth-coordinate. If the screen point - * cannot be sucessfully mapped, this will return null. - * - * @param windowPoint the window coordinate Point to project. - * @return the mapped screen coordinate Point. - * @throws IllegalArgumentException if windowPoint is null. - */ - Vec4 unProject(Vec4 windowPoint); - - /** - * Defines and applies a new model-view matrix in which the world origin is located at referenceCenter. - * Geometry rendered after a call to pushReferenceCenter should be transformed with respect to - * referenceCenter, rather than the canonical origin (0, 0, 0). Calls to - * pushReferenceCenter must be followed by {@link #popReferenceCenter} after rendering is complete. - * Note that calls to {@link #getModelViewMatrix} will not return reference-center model-view matrix, but the - * original matrix. - * - * @param dc the current World Wind drawing context on which new model-view state will be applied. - * @param referenceCenter the location to become the new world origin. - * @return a new model-view matrix with origin is at referenceCenter, or null if this method failed. - * @throws IllegalArgumentException if referenceCenter is null, if dc is null, or if the - * Globe or GL instances in dc are null. - */ - Matrix pushReferenceCenter(DrawContext dc, Vec4 referenceCenter); - - /** - * Removes the model-view matrix on top of the matrix stack, and restores the original matrix. - * - * @param dc the current World Wind drawing context on which the original matrix will be restored. - * @throws IllegalArgumentException if dc is null, or if the Globe or GL - * instances in dc are null. - */ - void popReferenceCenter(DrawContext dc); - - /** - * Gets the 'model-view' matrix computed in apply(), which transforms model coordinates to eye - * coordinates (where the eye is located at the origin, facing down the negative-z axis). This matrix is constructed - * using the model space translation and orientation specific to each implementation of View. - * - * @return the current model-view matrix. - */ - Matrix getModelViewMatrix(); - - /** - * Gets the 'projection' matrix computed in apply(), which transforms eye coordinates to screen - * coordinates. This matrix is constructed using the projection parameters specific to each implementation of - * View (e.g. field-of-view). The {@link #getFrustum} method returns the geometry corresponding to this - * matrix. - * - * @return the current projection matrix. - */ - Matrix getProjectionMatrix(); - - /** - * Gets a Rectangle representing the window bounds (x, y, width, height) of the viewport, computed in - * apply(). Implementations of View will configure themselves to render in this viewport. - * - * @return the current window bounds of the viewport. - */ - java.awt.Rectangle getViewport(); - - /** - * Gets the viewing Frustum in eye coordinates, computed in apply(). The - * Frustum is the portion of viewable space defined by three sets of parallel 'clipping' planes. The - * method {@link #getFrustumInModelCoordinates} maintains the shape of this Frustum, but it has been - * translated and aligned with the eye in model space. - * - * @return the current viewing frustum in eye coordinates. - */ - Frustum getFrustum(); - - /** - * Gets the viewing Frustum transformed to model coordinates. Model coordinate frustums are useful for - * performing visibility tests against world geometry. - * - * @return the current viewing frustum in model coordinates. - */ - Frustum getFrustumInModelCoordinates(); - - /** - * Gets the horizontal field-of-view angle (the angle of visibility) associated with this View, or null - * if the View implementation does not support a field-of-view. - * - * @return horizontal field-of-view angle, or null if none exists. - */ - Angle getFieldOfView(); - - /** - * Sets the horiziontal field-of-view angle (the angle of visibillity) associated with this View. This - * call may be ignored by implementations that do not support a field-of-view. - * - * @param newFov the new horizontal field-of-view angle. - * @throws IllegalArgumentException if newFov is null. - */ - void setFieldOfView(Angle newFov); - - /** - * Gets the View eye position in model coordinates. - * - * @return the eye position in model coordinates. - */ - Vec4 getEyePoint(); - - /** - * Gets the position of the View eye point in geographic coordinates. - * - * @return the geographic coordinates of the eye point. - */ - Position getEyePosition(); - - /** - * Gets the View y-axis orientation in model coordinates. - * - * @return the y-axis vector in model coordinates. - */ - Vec4 getUpVector(); - - /** - * Gets the View z-axis orientation in model coordinates. - * - * @return the z-axis vector in model coordinates. - */ - Vec4 getForwardVector(); - - /** - * Computes a line, in model coordinates, originating from the eye point, and passing throught the point contained - * by (x, y) on the View's projection plane (or after projection into model space). - * - * @param x the horizontal coordinate originating from the left side of View's projection plane. - * @param y the vertical coordinate originating from the top of View's projection plane. - * @return a line beginning at the View's eye point and passing throught (x, y) transformed into model - * space. - */ - Line computeRayFromScreenPoint(double x, double y); - - /** - * Computes the intersection of a line originating from the eye point (passing throught (x, y)) with the last - * rendered SectorGeometry, or the last analytical Globe if no rendered geometry exists. - * - * @param x the horizontal coordinate originating from the left side of View's projection plane. - * @param y the vertical coordinate originating from the top of View's projection plane. - * @return the point on the surface in polar coordiantes. - */ - Position computePositionFromScreenPoint(double x, double y); - - /** - * Computes the screen-aligned dimension (in meters) that a screen pixel would cover at a given distance (also in - * meters). This computation assumes that pixels dimensions are square, and therefore returns a single dimension. - * - * @param distance the distance from the eye point, in eye coordinates, along the z-axis. This value must be - * positive but is otherwise unbounded. - * @return the dimension of a pixel (in meters) at the given distance. - * @throws IllegalArgumentException if distance is negative. - */ - double computePixelSizeAtDistance(double distance); - - /** - * Gets the distance from the View's eye point to the horizon point on the last rendered - * Globe. - * - * @return the distance from the eye point to the horizon (in meters). - */ - double computeHorizonDistance(); - - /** - * Iterates over View state changes in ViewStateIterator and applies them to the - * View. The View will automatically refresh and request state from - * viewStateIterator until the iteration is complete, or View has been stopped by invoking - * {@link #stopStateIterators}. - * - * @param viewStateIterator the ViewStateIterator to iterate over. - */ - void applyStateIterator(ViewStateIterator viewStateIterator); - - /** - * Returns true when View is actively iterating over an instance of ViewStateIterator. - * - * @return true when iterating over ViewStateIterator; false otherwise. - */ - boolean hasStateIterator(); - - /** - * Immediately stops all active iteration over ViewStateIterator. - */ - void stopStateIterators(); -} diff --git a/gov/nasa/worldwind/view/ViewStateIterator.java b/gov/nasa/worldwind/view/ViewStateIterator.java deleted file mode 100644 index 655c9d5..0000000 --- a/gov/nasa/worldwind/view/ViewStateIterator.java +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright (C) 2001, 2006 United States Government as represented by -the Administrator of the National Aeronautics and Space Administration. -All Rights Reserved. -*/ -package gov.nasa.worldwind.view; - -/** - * An iteration over View state changes. - * - * @author dcollins - * @version $Id: ViewStateIterator.java 2422 2007-07-25 23:07:49Z tgaskins $ - * @see View - */ -public interface ViewStateIterator -{ - /** - * If possible, merges this ViewStateIterator with stateIterator and returns the result. - * - * @param view the View context. - * @param stateIterator the ViewStateIterator to merge with. - * @return the merged ViewStateIterator. - * @throws IllegalArgumentException if view or stateIterator are null. - */ - ViewStateIterator coalesceWith(View view, ViewStateIterator stateIterator); - - /** - * Returns true if ViewStateIterator has more state changes. - * - * @param view the View context. - * @return true if ViewStateIterator has more state changes; false otherwise. - */ - boolean hasNextState(View view); - - /** - * Applies the the next viewing state change to view. - * - * @param view the View context. - */ - void nextState(View view); -} -- 2.11.4.GIT