/* TerrainViewer.java A 3D topography viewing program. by M.A.Dubson, last update 3/17/99 ENVD 3252 1st mini-project */ import java.awt.*; import java.applet.Applet; import java.awt.event.*; public class TerrainViewer1 extends Applet implements MouseListener, MouseMotionListener { int w, h; // screen width, height in pixels int x,y; //present position of cursor int xLast, yLast; //last position of cursor int highness; // altitude values of elements of altitude array int alt; double heightFactor; // factor by which z is scaled int heightStep; //nbr of pixels between allowed heights int nbrHeights; //nbr of different altitude values int xArray, yArray; //x,y coordinates of element in altitude array double xD[][], yD[][], zD[][]; //double-valued x,y,z coordinates of rotated points double xDold[][], yDold[][], zDold[][]; int origin_X, origin_Y; //x, y coordinates of center of drawing canvas int redValue, greenValue, blueValue; int redY[], greenY[], blueY[]; //arrays for mapping x-position to RGB values int altitude[][]; //screen xy array of altitudes int altitudeOld[][]; //temporary storage of previous altitude array int pixWidth;//pixel width of element of altitude array int maxArrayX, maxArrayY; //dimensions of altitude array int nbrPixels; //total number of elements in altitude array int xOrder[], yOrder[]; //used to sort pixels for drawing double theta; //single step angle of rotation (in radians) about z-axis double theta_tot; // total angle of rotation (in degrees) double phi; //single step angle of tilt about x-axis double phi_tot; // total tilt about x-axis (in degrees) public void init() //initialize variables { addMouseListener(this); addMouseMotionListener(this); w = getSize().width; h = getSize().height; heightStep = 20; nbrHeights = h/heightStep; heightFactor = 0.8; redY = new int[nbrHeights]; greenY = new int[nbrHeights]; blueY = new int[nbrHeights]; redValue = 0; greenValue = 0; blueValue = 0; pixWidth = 10; theta = 0.174532925; //rotate by 10 degrees theta_tot = 0.0; phi = 0.0; phi_tot = 0.0; maxArrayX = (19*w/20)/pixWidth; //make altitude array elements pixWidth wide. maxArrayY = (19*h/20)/pixWidth; nbrPixels = maxArrayX*maxArrayY; origin_X = maxArrayX/2; origin_Y = maxArrayY/2; xD = new double [maxArrayX][maxArrayY]; yD = new double [maxArrayX][maxArrayY]; zD = new double [maxArrayX][maxArrayY]; xDold = new double [maxArrayX][maxArrayY]; yDold = new double [maxArrayX][maxArrayY]; zDold = new double [maxArrayX][maxArrayY]; altitude = new int[maxArrayX][maxArrayY]; altitudeOld = new int[maxArrayX][maxArrayY]; xOrder = new int[nbrPixels]; yOrder = new int[nbrPixels]; int i = 0; // initial drawing order for (int xL = 0; xL < maxArrayX; xL++) { for (int yL = 0; yL < maxArrayY; yL++) { xOrder[i]=xL; yOrder[i]= yL; i++; } }//end of initial drawing order loop for (int xL = 0; xL < maxArrayX; xL++) //initialize x,y,z coordinate arrays { for (int yL = 0; yL < maxArrayY; yL++) { xD[xL][yL] = (double)xL - origin_X; yD[xL][yL] = (double)(origin_Y - yL); zD[xL][yL] = 0.0; altitude[xL][yL] = 0; } } for( int y_scrn = 0; y_scrn < nbrHeights ; y_scrn ++ ) //Load colors into RGB arrays and draw color bar { if (y_scrn < nbrHeights/4){ redValue=255; greenValue = 4*255*y_scrn/nbrHeights; blueValue=0; } else if (y_scrn >= nbrHeights/4 && y_scrn < nbrHeights/2){ redValue = 255 - 4*255*(y_scrn-nbrHeights/4)/nbrHeights; greenValue = 255; blueValue=0; } else if (y_scrn >= nbrHeights/2 && y_scrn < 3*nbrHeights/4){ redValue=0; greenValue = 255; blueValue=4*255*(y_scrn-nbrHeights/2)/nbrHeights; } else if (y_scrn >= 3*nbrHeights/4){ redValue=0; greenValue = 255 - 4*255*(y_scrn-3*nbrHeights/4)/nbrHeights; blueValue=255; } //System.out.println("y-value is " + y + " RGB is "+redValue+" "+greenValue+" "+blueValue ); highness = nbrHeights - y_scrn - 1; redY[highness]=redValue; greenY[highness]=greenValue; blueY[highness]=blueValue; }//end of for y_scrn loop System.out.println("Height is " + h + "."); System.out.println("Width is " + w + "."); }//end of init method public void paint(Graphics g) { for (int y_scrn = 0; y_scrn < nbrHeights ; y_scrn++) //paint height bar on right { highness = nbrHeights - y_scrn -1; redValue = redY[highness]; greenValue = greenY[highness]; blueValue = blueY[highness]; g.setColor(new Color( redValue, greenValue, blueValue)); g.fillRect(19*w/20,y_scrn*heightStep,w/20,heightStep); }//end of painting height bar for ( int i=0; i < nbrPixels -1 ; i++ ) { for ( int j = 0; j < nbrPixels - 1 - i ; j++ ) { int xL = xOrder[j]; int yL = yOrder[j]; int xLnxt = xOrder[j+1]; int yLnxt = yOrder[j+1]; if ( zD[xL][yL] > zD[xLnxt][yLnxt] ) { double ztemp = zD[xL][yL]; int alttemp = altitude[xL][yL]; double xtemp = xD[xL][yL]; double ytemp = yD[xL][yL]; zD[xL][yL] = zD[xLnxt][yLnxt]; altitude[xL][yL] = altitude[xLnxt][yLnxt]; xD[xL][yL] = xD[xLnxt][yLnxt];yD[xL][yL] = yD[xLnxt][yLnxt]; zD[xLnxt][yLnxt]= ztemp; altitude[xLnxt][yLnxt] = alttemp; xD[xLnxt][yLnxt]= xtemp; yD[xLnxt][yLnxt]= ytemp; } } } for (int i=0; i < nbrPixels; i++) { int xL = xOrder[i]; int yL = yOrder[i]; highness = altitude[xL][yL]; redValue = redY[highness]; greenValue = greenY[highness]; blueValue = blueY[highness]; //int xScreen = origin_X + (int)Math.round(xD[xL][yL]); //int yScreen = origin_Y - (int)Math.round(yD[xL][yL]); int xScrn = origin_X*pixWidth + (int)(Math.round(xD[xL][yL]*(double)pixWidth)); int yScrn = origin_Y*pixWidth - (int)(Math.round(yD[xL][yL]*(double)pixWidth)); g.setColor(new Color( redValue, greenValue, blueValue)); g.fillRect(xScrn-1, yScrn, pixWidth+2, (1)*pixWidth); } g.setColor(Color.yellow); g.fillRect(0,19*h/20-1,19*w/20,h/20); g.setColor(Color.black); g.drawRect(0,19*h/20-1,19*w/80,h/20); g.drawRect(19*w/80,19*h/20-1,19*w/80,h/20); g.drawRect(38*w/80,19*h/20-1,19*w/80,h/20); g.drawRect(57*w/80,19*h/20-1,19*w/80,h/20); g.setFont(new Font("Times", Font.PLAIN, 12)); g.drawString("Rotate CW", w/40, 79*h/80); g.drawString("Rotate CCW", 20*w/80, 79*h/80); g.drawString("Tilt +", 42*w/80, 79*h/80); g.drawString("Tilt -", 61*w/80, 79*h/80); //System.out.println("zD at (0,0) is " + zD[0][0]+ "."); //System.out.println("blueValue(highness = 0) is " + blueY[0] + "."); //g.setColor(Color.black); // draw small oval at rotation center //g.fillOval(origin_X*pixWidth - 2, origin_Y*pixWidth - 2, 4 , 4 ); }//end of paint method public void mousePressed( MouseEvent e ) { x=e.getX(); y=e.getY(); xArray = x/pixWidth; yArray = y/pixWidth; if ( x > 19*w/20) { int y_scrn = y/heightStep; highness = nbrHeights - y_scrn - 1; //necessary because y(screen coord) increases going down redValue = redY[highness]; greenValue = greenY[highness]; blueValue = blueY[highness]; System.out.println("Highness is " + highness + "."); Graphics g = getGraphics(); g.setColor(new Color( redY[0], greenY[0], blueY[0])); g.fillRect(19*w/20,(nbrHeights - 1)*heightStep,w/20,heightStep); g.setColor(Color.yellow); g.setFont(new Font("Times", Font.PLAIN, 12)); g.drawString(""+highness, 77*w/80, 79*h/80); } else if (y > 19*h/20 && x < 38*w/80)//if press theta rotation keys { if (x<19*w/80) { theta = -0.174532925; theta_tot += theta*57.29577951; System.out.println("Rotation angle is " + theta_tot + " degrees."); } else if (x<38*w/80) { theta = +0.174532925; theta_tot += theta*57.29577951; System.out.println("Rotation angle is " + theta_tot + " degrees."); } //System.out.println("Rotation started."); for (int xL = 0; xL < maxArrayX; xL++) // xL for "x in Loop" { for (int yL = 0; yL < maxArrayY; yL++) { xDold[xL][yL] = xD[xL][yL]; //store array values in temp array yDold[xL][yL] = yD[xL][yL]; zDold[xL][yL] = zD[xL][yL]; } } for (int xL = 0; xL < maxArrayX; xL++) { for (int yL = 0; yL < maxArrayY; yL++) { xD[xL][yL] = Math.cos(theta)*xDold[xL][yL] - Math.sin(theta)*yDold[xL][yL]; yD[xL][yL] = Math.sin(theta)*xDold[xL][yL] + Math.cos(theta)*yDold[xL][yL]; /*if ((int)zD[xL][yL] != 0) { System.out.println( "Old x is " + xDold[xL][yL] + ". Old y is " + yDold[xL][yL] + "."); System.out.println( "Rot x is " + xD[xL][yL] + ". Rot y is " + yD[xL][yL] + "."); }*/ } } //System.out.println("Rotation finished."); repaint(); } //end of theta rotation loop else if ( y > 19*h/20 && x > 38*w/80) //if press phi rotation keys { if ( x < 57*w/80) { phi = 0.087266463; phi_tot -= phi*57.29577951; System.out.println("Tilt angle is " + phi_tot + " degrees."); } else if ( x < 76*w/80 ) { phi = -0.087266463; phi_tot -= phi*57.29577951; System.out.println("Tilt angle is " + phi_tot + " degrees."); } //System.out.println("Rotation started."); for (int xL = 0; xL < maxArrayX; xL++) // xL for "x in Loop" { for (int yL = 0; yL < maxArrayY; yL++) { xDold[xL][yL] = xD[xL][yL]; //store array values in temp array yDold[xL][yL] = yD[xL][yL]; zDold[xL][yL] = zD[xL][yL]; } } for (int xL = 0; xL < maxArrayX; xL++) { for (int yL = 0; yL < maxArrayY; yL++) { yD[xL][yL] = Math.cos(phi)*yDold[xL][yL] - Math.sin(phi)*zDold[xL][yL]; zD[xL][yL] = Math.sin(phi)*yDold[xL][yL] + Math.cos(phi)*zDold[xL][yL]; /*if (altitude[xL][yL] != 0) { System.out.println( "Old x is " + xDold[xL][yL] + ". Old y is " + yDold[xL][yL] + "."); System.out.println( "Rot x is " + xD[xL][yL] + ". Rot y is " + yD[xL][yL] + "."); }*/ } } //System.out.println("Rotation finished."); repaint(); }// end of phi rotation loop else { Graphics g = getGraphics(); g.setColor(new Color(redValue, greenValue, blueValue)); g.fillRect((xArray * pixWidth), (yArray * pixWidth), pixWidth, pixWidth); xD[xArray][yArray]= (double)(xArray - origin_X); yD[xArray][yArray]= (double)(origin_Y - yArray); zD[xArray][yArray] = (double) heightFactor * highness; altitude[xArray][yArray] = highness; xLast = x; yLast = y; } }//end of mousePressed method public void mouseDragged( MouseEvent e ) { x = e.getX(); y = e.getY(); xArray = x/pixWidth; yArray = y/pixWidth; if (x < 19*w/20) { Graphics g = getGraphics(); g.setColor(new Color(redValue, greenValue, blueValue)); g.fillRect((xArray * pixWidth), (yArray * pixWidth), pixWidth, pixWidth); xD[xArray][yArray]= (double)(xArray - origin_X); yD[xArray][yArray]= (double)(origin_Y - yArray); zD[xArray][yArray] = (double) heightFactor*highness; altitude[xArray][yArray] = highness; //altitudeOld[xArray][yArray] = highness; //g.drawLine(xLast, yLast, x, y); xLast = x; yLast = y; //System.out.println("xArray is "+ xArray + ". yArray is " + //yArray + "." + " Altitude is " + highness + "."); } }//end of mouseDragged method public void mouseMoved( MouseEvent e ) {;} public void mouseReleased( MouseEvent e ) {;} public void mouseClicked( MouseEvent e ) {;} public void mouseEntered( MouseEvent e ) {;} public void mouseExited( MouseEvent e ) {;} }//end of class TerrainViewer