home *** CD-ROM | disk | FTP | other *** search
Java Source | 1999-07-02 | 16.3 KB | 659 lines |
- /*
- * @(#)Panorama.java 1.1 98/04/12
- *
- * Copyright (c) 1998, David Griffiths. All Rights Reserved.
- *
- * This software is the proprietary information of David Griffiths.
- * This source code may not be published or redistributed without the
- * express permission of the author.
- *
- * THE AUTHOR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY
- * OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, OR NON-INFRINGEMENT. THE AUTHOR SHALL NOT BE LIABLE FOR ANY DAMAGES
- * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
- * THIS SOFTWARE OR ITS DERIVATIVES.
- *
- */
-
- import java.awt.*;
- import java.applet.Applet;
- import java.io.*;
- import java.net.*;
-
- public synchronized class Panorama extends Applet implements Runnable {
- private Graphics screenG;
- private Image screenImage, theImage;
- private int dx[][], dy[][], dw[], cx, cy, w1, h1, w2, h2, mx, my, mxOrig, myOrig;
- private int moveX, moveY;
- private int renderRate, degrees, sw, sh, needDetail, timeSample, rotateAmount;
- private boolean interlace, jdk10, mouseMoving, autoRotate, autoRotateOn;
- private boolean imageLoading = false;
- private int hyperLink = -1;
- private Color tipColour = new Color(255, 255, 225);
- private FontMetrics screenFM;
- private DataInputStream mapIn;
- private final static int HYPER_COUNT = 10;
- private Polygon hyperArea[] = new Polygon[HYPER_COUNT];
- private String tip[] = new String[HYPER_COUNT];
- private String href[] = new String[HYPER_COUNT];
- private int polyCount = 0;
- private int pointx[] = new int[255], pointy[] = new int[255], coordNo;
- private Thread thrMain;
- transient private long totTime = 0L;
- transient private int totPass = 0;
- transient private Graphics gMain;
- private int rotateSpeed = 3;
-
- /**
- * Constructors.
- */
- public Panorama() {
- super();
-
- dx = new int[600][600];
- dy = new int[600][600];
- dw = new int[600];
-
- if (!System.getProperty("java.version").substring(0,3).equals("1.0"))
- try {
- Class paras[] = {
- Image.class,
- Integer.TYPE,
- Integer.TYPE,
- Integer.TYPE,
- Integer.TYPE,
- Integer.TYPE,
- Integer.TYPE,
- Integer.TYPE,
- Integer.TYPE,
- java.awt.image.ImageObserver.class
- };
- jdk10 = false;
- java.awt.Graphics.class.getMethod("drawImage",
- paras);
- }
- catch (Exception e) {
- jdk10 = true;
- }
- else
- jdk10 = true;
- // jdk10 = true;
- }
-
- public Panorama(Image theImage) {
- this(360, theImage);
- }
-
- public Panorama(int degrees, Image theImage) {
- this(360, theImage, 300, 200);
- }
-
- public Panorama(int degrees, Image theImage, int sw, int sh) {
- this();
- this.degrees = degrees;
- this.theImage = theImage;
- this.sw = sw;
- this.sh = sh;
-
- resize(this.sw, this.sh);
- }
-
- /**
- * Runnable section.
- *
- * The following methods are here to implement the Runnable interface.
- */
- public void start() {
- if (thrMain == null) {
- thrMain = new Thread(this);
- thrMain.start();
- }
- }
-
- public void stop() {
- if (thrMain != null) {
- thrMain.stop();
- thrMain = null;
- }
- }
-
- public void run() {
- gMain = getGraphics();
- while (true) {
- if ((autoRotateOn) && (!mouseMoving)) {
- needDetail = renderRate;
- // moveX = 10;
- moveX = rotateSpeed;
- }
- if (!alreadyPainting)
- repaint();
- try {
- Thread.sleep(50);
- }
- catch (InterruptedException e2) {
- stop();
- }
- }
- }
-
- /**
- * preferredSize() method used for when the class is a component.
- */
- public Dimension preferredSize() {
- return new Dimension(300, 200);
- }
-
- public void setAutoRotate(int speed) {
- autoRotate = !(speed == 0);
- autoRotateOn = autoRotate;
- rotateSpeed = speed;
- }
-
- public void init() {
- String string, mapName;
-
- string = getParameter("autorotate");
- if (string != null)
- // setAutoRotate(string.toUpperCase().equals("ON"));
- setAutoRotate(Integer.parseInt(string));
- else
- // setAutoRotate(false);
- setAutoRotate(0);
- string = getParameter("degrees");
- if (string != null)
- degrees = Integer.parseInt(string);
- else
- degrees = 360;
- theImage = getImage(getDocumentBase(), getParameter("image"));
- sw = size().width;
- sh = size().height;
- mouseMoving = false;
- mapName = getParameter("map");
- if (mapName != null)
- openImageMap(mapName);
- }
-
- synchronized private void createScreenImage() {
- if (screenImage != null)
- return;
- MediaTracker mediaTracker = new MediaTracker(this);
- mediaTracker.addImage(this.theImage, 0);
- try {
- mediaTracker.waitForID(0);
- }
- catch (Exception e) {}
- w1 = sw;
- w2 = theImage.getWidth(this);
- h1 = sh;
- h2 = theImage.getHeight(this);
- screenImage = createImage(w2 + sw + (w2 / 4), h2);
- screenG = screenImage.getGraphics();
- screenG.drawImage(theImage, sw, 0, this);
- screenG.drawImage(theImage, sw + w2, 0, this);
- screenG.setFont(new Font("Helvetica", Font.PLAIN, 11));
- screenFM = screenG.getFontMetrics();
- initialise();
- }
-
- private void initialise() {
- int k = (int)((double)w2 / ((double)(degrees / 180) * 3.1415926));
- int oldyd;
-
- resetView();
- if (w1 > dx.length)
- w1 = dx.length;
- if (h2 > dy.length)
- h2 = dy.length;
- for (int i = 0; i < w1; i++) {
- for (int j = 0; j < h2; j++) {
- double d1 = i - w1 / 2;
- double d2 = h2 / 2 - j;
- double d3 = (double)k * Math.atan(d1 / k);
- double d5 = d1;
- d5 *= d5;
- d5 += k * k;
- d5 = Math.sqrt(d5);
- double d4 = d2 * k / d5;
- dx[i][j] = (int)d3;
- dy[i][j] = (int)d4;
- }
- }
- oldyd = 0;
- for (int i = w1; --i >= 0;) {
- if (dy[i][0] == oldyd) {
- dw[i] = dw[i + 1] + 1;
- }
- else {
- oldyd = dy[i][0];
- dw[i] = 1;
- }
- }
-
- renderRate = 1;
- interlace = true;
- needDetail = renderRate;
- }
-
- public void update(Graphics g) {
- paint(g);
- }
-
- boolean alreadyPainting = false;
-
- public void paint(Graphics g) {
- if (alreadyPainting)
- return;
- alreadyPainting = true;
- if (screenImage == null) {
- g.setFont(new Font("Helvetica", 20, Font.PLAIN));
- String loadCaption = "Panorama Loading...";
- FontMetrics fm = g.getFontMetrics();
- int tw = fm.stringWidth(loadCaption);
- int th = fm.getHeight();
- g.setColor(Color.lightGray);
- g.fillRect(0, 0, sw, sh);
- g.setColor(Color.white);
- g.drawString(loadCaption, (sw - tw) / 2, (sh + th) / 2);
- g.setColor(Color.black);
- g.drawString(loadCaption, ((sw - tw) / 2) + 2, ((sh + th) / 2) + 2);
- g.setColor(Color.lightGray);
- g.drawString(loadCaption, ((sw - tw) / 2) + 1, ((sh + th) / 2) + 1);
- if (!imageLoading) {
- imageLoading = true;
- createScreenImage();
- repaint();
- }
- }
- else {
- if (jdk10) {
- oldPaint(g);
- }
- else {
- renderImage(g, 1, 0, interlace);
- }
- if (hyperLink != -1) {
- drawTip(tip[hyperLink]);
- }
- g.drawImage(screenImage, 0, 0, this);
- }
- if ((moveX != 0) && (w1 > 0))
- moveHoriz(moveX * w2 / (w1 << 4));
- if ((moveY != 0) && (w1 > 0))
- moveVert(moveY * w2 / (w1 << 4));
- if ((moveX != 0) || (moveY != 0)) {
- needDetail = renderRate;
- }
- alreadyPainting = false;
- }
-
- /**
- * Methods for JDK1.0 (or for browsers which don't use full
- * full JDK1.1).
- */
- public void oldPaint(Graphics g) {
- long startTime = 0L;
- long stopTime = 0L;
- long minTime = 10000L;
- startTime = System.currentTimeMillis();
- oldRenderImage(g, renderRate, needDetail, interlace);
- stopTime = System.currentTimeMillis();
- if (minTime > (stopTime - startTime))
- minTime = (stopTime - startTime);
- if ((renderRate < 8) && (minTime > 100L) && (stopTime != startTime)) {
- renderRate++;
- }
- // rotateAmount = 3 * (int)minTime / 50;
- rotateAmount = rotateSpeed * (int)minTime / 50;
- }
-
- private void oldRenderImage(Graphics g, int renderRate, int needDetail, boolean interlace) {
- int yd = renderRate;
- int xd = renderRate;
- int xinc = 1;
-
- yd = needDetail * h2 / (h2 - h1);
- for (int x1 = 0; x1 < w1; x1 = x1 + xinc) {
- if (dw[x1] > needDetail)
- xinc = dw[x1];
- else
- xinc = needDetail;
- for (int y1 = 0; y1 < h1; y1 += yd) {
- int xoff = cx + dx[x1][cy + y1];
- int yoff = h2 / 2 - dy[x1][cy + y1];
- if (xoff >= w2) {
- xoff = xoff - w2;
- }
- else if (xoff < 0) {
- xoff = xoff + w2;
- }
- if ((x1 + xinc) < sw)
- screenG.copyArea(xoff + sw, yoff,
- xinc, yd,
- x1 - xoff - sw, y1 - yoff);
- else
- screenG.copyArea(xoff + sw, yoff,
- sw - x1, yd,
- x1 - xoff - sw, y1 - yoff);
- }
- }
- }
-
- /**
- * renderImage used by JDK1.1 browsers.
- */
- public void renderImage(Graphics g, int i1, int j1, boolean interlace) {
- int x1;
- int xd;
- int yd;
- xd = 1;
- yd = 50;
- for (x1 = j1; x1 < w1; x1 += dw[x1]) {
- int xoff = cx + dx[x1][cy + h1];
- int yoff = (h2 / 2) - dy[x1][cy + h1];
- if (xoff >= w2) {
- xoff = xoff - w2;
- }
- else if (xoff < 0) {
- xoff = xoff + w2;
- }
- screenG.drawImage(screenImage, x1, 0,
- x1 + dw[x1], sh,
- xoff + sw, h2 / 2 - dy[x1][cy],
- xoff + dw[x1] + sw, yoff,
- this);
- }
- }
-
- //////////////////////////////////////////
- //
- // INTERACTIVITY SECTION
- //
- //////////////////////////////////////////
- public boolean mouseDown(Event event, int i, int j) {
- mouseMoving = true;
- mxOrig = mx = i;
- myOrig = my = j;
- moveX = moveY = 0;
- checkCursor(i, j);
- return true;
- }
-
- public boolean mouseUp(Event event, int i, int j) {
- if ((mxOrig == i) && (myOrig == j) && (autoRotate))
- autoRotateOn = !autoRotateOn;
- mouseMoving = false;
- needDetail = 1;
- moveX = moveY = 0;
- checkCursor(i, j);
- if ((mxOrig == i) && (myOrig == j) && (hyperLink != -1))
- openDoc(href[hyperLink]);
- return false; // Return false because we want the message passed up to the parent.
- }
-
- private void openDoc(String s) {
- try {
- URL uRL = new URL(getDocumentBase(), s);
- getAppletContext().showDocument(uRL, "_self");
- }
- catch (MalformedURLException e) {
- getAppletContext().showStatus("Bad URL: " + s);
- }
- }
-
- public boolean mouseDrag(Event event, int i, int j) {
- if (i != mx)
- moveX += (i - mx);
- if (j != my)
- moveY += (j - my);
- mx = i;
- my = j;
- return true;
- }
-
- public boolean mouseMove(Event event, int i, int j) {
- checkCursor(i, j);
- return true;
- }
-
- //////////////////////////////////////////
- //
- // MOVEMENT SECTION
- //
- //////////////////////////////////////////
- public void resetView() {
- cx = w2 / 2;
- cy = h2 / 2 - h1 / 2;
- }
-
- private void moveVert(int i) {
- if ((cy + i) >= 0 && (cy + i) < (h2 - h1))
- cy = cy + i;
- }
-
- private void moveHoriz(int i) {
- cx += i;
- if (cx < 0)
- cx = cx + w2;
- else if (cx >= w2)
- cx = cx - w2;
- }
-
- public int getHorizontalPos() {
- return cx;
- }
-
- //////////////////////////////////////////
- //
- // HYPERGRAPHICS SECTION
- //
- //////////////////////////////////////////
- private void openImageMap(String mapName) {
- String line = "", map = "", coords="";
- boolean inMap = false;
- int pos1, pos2;
-
- try {
- InputStream In = getDocumentBase().openStream();
- mapIn = new DataInputStream(new BufferedInputStream(In));
- line = mapIn.readLine();
- while (line != null) {
- if (line.toUpperCase().indexOf("<MAP") != -1) {
- if (line.toUpperCase().indexOf("NAME=\""
- + mapName.toUpperCase() + "\"") != -1) {
- map = line;
- inMap = true;
- }
- }
- else if (inMap) {
- map = map + line;
- }
- if (line.indexOf("</MAP") != -1) {
- inMap = false;
- }
- line = mapIn.readLine();
- }
- }
- catch (IOException e) {
- System.out.println("IO Error: " + e.getMessage());
- }
- if (map.length() > 0) {
- pos1 = map.toUpperCase().indexOf("<AREA") + "<AREA".length();
- while (pos1 >= "<AREA".length()) {
- pos2 = map.indexOf(">", pos1);
- coords = map.substring(pos1, pos2);
- if (pos2 > pos1) {
- createArea(coords, polyCount++);
- }
- map = map.substring(pos1);
- pos1 = map.toUpperCase().indexOf("<AREA") + "<AREA".length();
- }
- }
- }
-
- private void createArea(String area, int hyperNo) {
- Polygon poly = null;
- String coords = "", shape = "", alt = "", href = "";
- if (area.length() > 0) {
- coords = getAttr(area, "COORDS");
- shape = getAttr(area, "SHAPE").toUpperCase();
- alt = getAttr(area, "ALT");
- href = getAttr(area, "HREF");
- if (shape.equals("RECT")) {
- poly = aRect(coords);
- }
- else if (shape.equals("POLYGON")) {
- poly = aPolygon(coords);
- }
- else if (shape.equals("CIRCLE")) {
- poly = aCircle(coords);
- }
- }
- hyperArea[hyperNo] = poly;
- tip[hyperNo] = alt;
- this.href[hyperNo] = href;
- }
-
- private String getAttr(String s, String attr) {
- String getAttr;
- int pos1, pos2;
-
- pos1 = s.toUpperCase().indexOf(attr.toUpperCase() + "=\"")
- + (attr + "=\"").length();
- getAttr = "";
- if (pos1 >= (attr + "=\"").length()) {
- pos2 = s.indexOf("\"", pos1);
- getAttr = s.substring(pos1, pos2);
- }
- return getAttr;
- }
-
- private Polygon aRect(String coords) {
- int px[] = new int[4], py[] = new int[4];
- getPoints(coords);
- px[0] = pointx[0]; px[1] = pointx[1]; px[2] = px[1]; px[3] = px[0];
- py[0] = pointy[0]; py[1] = pointy[0]; py[2] = pointy[1]; py[3] = py[2];
- return new Polygon(px, py, 4);
- }
-
- private Polygon aCircle(String coords) {
- String temp = coords + ",0"; // Dummy value so we can get an even # of coords
- int x, y, radius;
- int px[] = new int[8], py[] = new int[8];
- getPoints(temp);
- x = pointx[0]; y = pointy[0]; radius = pointx[1];
- for (int i = 0; i < px.length; i++) {
- px[i] = x + (int)(radius * Math.cos(2 * 3.1415926 * (double)i / (double)px.length));
- py[i] = y + (int)(radius * Math.sin(2 * 3.1415926 * (double)i / (double)px.length));
- }
- return new Polygon(px, py, px.length);
- }
-
- private Polygon aPolygon(String coords) {
- String temp;
- getPoints(coords);
- return new Polygon(pointx, pointy, coordNo);
- }
-
- private void getPoints(String coords) {
- String temp = coords + ",";
- int pos1 = temp.indexOf(',');
- coordNo = 0;
- while (pos1 != -1) {
- pointx[coordNo] = Integer.parseInt(temp.substring(0, pos1));
- temp = temp.substring(pos1 + 1).trim();
- pos1 = temp.indexOf(',');
- pointy[coordNo++] = Integer.parseInt(temp.substring(0, pos1));
- temp = temp.substring(pos1 + 1).trim();
- pos1 = temp.indexOf(',');
- }
- }
-
- private void checkCursor(int i, int j) {
- if (mouseMoving) {
- if (!jdk10)
- setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
- hyperLink = -1;
- return;
- }
-
- int xoff = cx + dx[i][cy + j];
- int yoff = h2 / 2 - dy[i][cy + j];
- if (xoff >= w2) {
- xoff = xoff - w2;
- }
- else if (xoff < 0) {
- xoff = xoff + w2;
- }
- Point p = new Point(xoff, yoff);
- for (int n = 0; n < polyCount; n++) {
- if (hyperArea[n].inside(p.x, p.y)) {
- if (!jdk10)
- setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
- hyperLink = n;
- repaint();
- return;
- }
- }
-
- if (!jdk10)
- setCursor(Cursor.getDefaultCursor());
- if (hyperLink != -1)
- repaint();
- hyperLink = -1;
- }
-
- //////////////////////////////////////////
- //
- // TIP SECTION
- //
- //////////////////////////////////////////
-
- private void drawTip(String msg) {
- int x, y, w, h, a, d, tw, bx, by, bw, bh;
- int border = 1;
- int maxWidth = 2 * sw / 3;
- int slice;
- String temp, disp, rest;
- int cutTo;
-
- a = screenFM.getAscent();
- d = screenFM.getHeight() - screenFM.getAscent();
- h = a + d + (border << 1);
- bx = bw = 0;
- bh = d;
- by = sh + 1;
- x = 20;
- y = 20;
- disp = msg;
- rest = "";
- while (!disp.equals("")) {
- tw = screenFM.stringWidth(disp);
- cutTo = disp.length();
- rest = "";
- if (tw > maxWidth) {
- slice = disp.length() * maxWidth / tw;
- temp = disp.substring(0, slice);
- cutTo = temp.lastIndexOf(' ');
- rest = disp.substring(cutTo + 1, disp.length());
- disp = disp.substring(0, cutTo + 1);
- }
-
- w = screenFM.stringWidth(disp) + (d << 1) + (border << 1);
- if (w > bw)
- bw = w;
- bh = bh + d + a;
- bx = x;
- if (y < by)
- by = y;
- screenG.setColor(tipColour);
- screenG.fillRect(x, y, bw, h);
- screenG.setColor(Color.black);
- screenG.drawString(disp, x + d + border, y + a + border);
- y = y + d + a;
- disp = rest;
- }
- screenG.drawRect(bx, by, bw, bh);
- }
- }
-