/***************************************************************************** * Web3d.org Copyright (c) 2001-2005 * Java Source * * This source is licensed under the BSD license. * Please read docs/BSD.txt for the text of the license. * * This software comes with the standard NO WARRANTY disclaimer for any * purpose. Use it at your own risk. If there's a problem you get to fix it. * ****************************************************************************/ import java.util.Map; import org.web3d.x3d.sai.*; import org.w3c.dom.*; import java.io.*; import java.util.*; import java.net.URL; /** * Example of how to take zips / city and teleport to the location * * @author Alan Hudson * @version */ public class LocationTeleporter implements X3DPerFrameObserverScript, X3DFieldEventListener, Runnable { private static final double[] HOME_POS = new double[] {0, 0, 50000000}; /** The current user pos, need GeoProximitySensor for this really */ private double[] currPos = new double[3]; /** The browser */ private Browser browser; /** The current scene */ private X3DExecutionContext scene; /** The destination position */ private double[] destPos; /** Should we interpolate to the new position */ private boolean interp = true; /** Are we interpolating to a position */ private boolean inInterp = false; /** The location of the box */ private SFString location; /** The position to goto */ private SFVec3d position; /** The viewpoint bind */ private SFBool bind; /** Scratch var */ private double[] newPos; /** The mapping loading thread */ private Thread mapLoader; /** City to lat/long */ private HashMap cityToLatLong = new HashMap (80000); /** Zipcode to lat/long */ private HashMap zipToLatLong = new HashMap(40000); public LocationTeleporter() { currPos[0] = HOME_POS[0]; currPos[1] = HOME_POS[1]; currPos[2] = HOME_POS[2]; newPos = new double[3]; } //---------------------------------------------------------- // Methods defined by X3DScriptImplementation //---------------------------------------------------------- public void setBrowser(Browser browser) { this.browser = browser; } public void setFields(X3DScriptNode externalView, Map fields) { // Get the fields we need for processing location = (SFString) fields.get("location"); position = (SFVec3d) fields.get("position"); bind = (SFBool) fields.get("bind"); location.addX3DEventListener(this); } public void initialize() { scene = browser.getExecutionContext(); loadZipTable(); } public void eventsProcessed() { } public void shutdown() { } public void prepareEvents() { if (inInterp) { double RATE = 0.03; double MIN_DEGREE = 0.1; double MIN_HEIGHT = 50000; double x = destPos[0] - currPos[0]; double y = destPos[1] - currPos[1]; double z = destPos[2] - currPos[2]; if (x < MIN_DEGREE && y < MIN_DEGREE && z < MIN_HEIGHT) { newPos[0] = destPos[0]; newPos[1] = destPos[1]; newPos[2] = destPos[2]; inInterp = false; } else { newPos[0] = currPos[0] + RATE * (destPos[0] - currPos[0]); newPos[1] = currPos[1] + RATE * (destPos[1] - currPos[1]); newPos[2] = currPos[2] + RATE * (destPos[2] - currPos[2]); } position.setValue(newPos); currPos[0] = newPos[0]; currPos[1] = newPos[1]; currPos[2] = newPos[2]; } } //---------------------------------------------------------- // Methods defined by X3DFieldEventListener //---------------------------------------------------------- public void readableFieldChanged(X3DFieldEvent evt) { String loc = location.getValue(); double[] pos2d = null; pos2d = cityToLatLong.get(loc.toUpperCase()); double[] pos3d = new double[3]; if (pos2d == null) pos2d = zipToLatLong.get(loc); if (pos2d != null) { System.out.println("Going to: " + loc + " lat: " + pos2d[0] + " long: " + pos2d[1]); pos3d[0] = pos2d[0]; pos3d[1] = pos2d[1]; pos3d[2] = 100000; currPos[0] = HOME_POS[0]; currPos[1] = HOME_POS[1]; currPos[2] = HOME_POS[2]; bind.setValue(true); if (!interp) { position.setValue(pos3d); } else { inInterp = true; destPos = pos3d; } } else { System.out.println("Can't find location: " + loc); } } private void loadZipTable() { mapLoader = new Thread(this, "Map Loader"); mapLoader.start(); } public void run() { System.out.print("Loading zip table"); int num = 0; try { BufferedReader br = null; String worldUrl = scene.getWorldURL(); String filename = "ZIP_CODES.txt"; URL url = new URL(worldUrl + filename); try { Object content = url.getContent(); if (content instanceof InputStream) { br = new BufferedReader(new InputStreamReader((InputStream)content)); } else { System.out.println("Can't handle content: " + content); } } catch(Exception e) { br = new BufferedReader(new FileReader(new File(filename))); } //File file = new File("test"); //FileReader fr = new FileReader(file); //BufferedReader br = new BufferedReader(fr); String line = ""; while(line != null) { line = br.readLine(); if (line != null) addZipEntry(line); num++; if (num % 100 == 0) System.out.print("."); } } catch(Exception e) { e.printStackTrace(); } System.out.println("\nDone loading zip table"); } /** * Add a zip entry. Line is a zip, lat long, city, state, county, zip_class * * @param line */ private void addZipEntry(String line) { //System.out.println(line); StringTokenizer strtok = new StringTokenizer(line, ","); String zip = null; String latitude = null; String longitude = null; String city = null; String state = null; String st; int field = 0; while(strtok.hasMoreTokens()) { switch(field) { case 0: zip = strtok.nextToken(); break; case 1: latitude = strtok.nextToken(); break; case 2: longitude = strtok.nextToken(); break; case 3: city = strtok.nextToken(); break; case 4: state = strtok.nextToken(); break; default: // ignore st = strtok.nextToken(); break; } field++; } try { double[] latlong = new double[2]; latlong[0] = Double.parseDouble(latitude.substring(1,latitude.length() -1)); latlong[1] = Double.parseDouble(longitude.substring(1,longitude.length() -1)); cityToLatLong.put(city.substring(1,city.length()-1).toUpperCase(), latlong); cityToLatLong.put(city.substring(1,city.length()-1).toUpperCase() + "," + state.substring(1, state.length() - 1).toUpperCase(), latlong); zipToLatLong.put(zip.substring(1,zip.length()-1).toUpperCase() , latlong); } catch(Exception e) { // ignore bad entries } } }