import java.util.*; import java.awt.*; public class skyline { public Vector myBuildings; Choice bldgInput = new Choice(); Choice bldgResults = new Choice(); skyline () { //create a new skyline myBuildings = new Vector(); } public void showBuildings(){ Enumeration e = myBuildings.elements(); while (e.hasMoreElements()){ Building b = (Building) e.nextElement(); System.out.println("ShowBuildings: "+b.toString()); } } public void urbanRenewal(){ //delete the last building - works in applet viewer, doesn't work in applet System.out.println("New Urban Renewal"); // myBuildings.removeElement(myBuildings.lastElement()); Vector v = (Vector) myBuildings.clone(); myBuildings=new Vector(); bldgInput = new Choice(); Enumeration e = v.elements(); Building lastBuilding = (Building) v.lastElement(); while (e.hasMoreElements()) { Building b = (Building) e.nextElement(); if ( (b.L == lastBuilding.L) & (b.H == lastBuilding.H) & (b.R == lastBuilding.R)){ //they are the same, don't add //System.out.println(b.toString()); } else { addBuilding(b.L,b.H,b.R); } } } public void addRectToPoly(Polygon poly, Rectangle r){ poly.addPoint(r.x,r.y+r.height); poly.addPoint(r.x,r.y); poly.addPoint(r.x+r.width,r.y); poly.addPoint(r.x+r.width,r.y+r.height); } public Polygon makeSkyline(int screenWidth, int screenHeight, int groundLevel){ Polygon poly = new Polygon(); int x,y = 0; int A,B; //translate skylinePoly into a scaled skylinePoly in 'poly' //return poly buildingVec = (Vector) myBuildings.clone(); computeSkyline(); //Robbie's code //invert y and scale from x,y to screen x,y. //this should _really_ be done more cleanly!! for (int i=0; i < skylinePoly.npoints; i++){ skylinePoly.xpoints[i] = skylinePoly.xpoints[i]*10; skylinePoly.ypoints[i] = (screenHeight-groundLevel)-(skylinePoly.ypoints[i]*10); } return skylinePoly; } public Polygon makeSkylineBox(int screenWidth, int screenHeight, int groundLevel){ Polygon poly = new Polygon(); Enumeration e = myBuildings.elements(); int x,y = 0; int A,B; //this creates a polygon of each corner of each square. while (e.hasMoreElements() ){ Building b = (Building) e.nextElement(); x=b.L*10; y=(screenHeight-groundLevel)-(b.H*10); A=x; B=screenHeight-groundLevel; poly.addPoint(A,B); B=y; poly.addPoint(A,B); A=x+(b.R*10)-(b.L*10); poly.addPoint(A,B); A=x+(b.R*10)-(b.L*10);B=screenHeight-groundLevel; poly.addPoint(A,B); //this closes this seqment, so that it ends on the ground. A=x; B=screenHeight-groundLevel; } return poly; } //makeSkylineBox public void addBuilding(int L, int H, int R){ //System.out.println("In addBuilding L="+L+" H="+H+" R="+R); //create a building Building bldg=new Building(L,H,R); myBuildings.addElement(bldg); bldgInput.addItem(bldg.toString()); //add it to the vector } public void updateInput(Choice c, Choice x){ //removeAll is JDK 1.1 - so it won't work on my favorite //version of netscape //c.removeAll(); // x = new Choice(); //c=null; //c = new Choice(); Enumeration e = myBuildings.elements(); while (e.hasMoreElements() ){ Building b = (Building) e.nextElement(); String st = b.toString(); boolean myFlag=true; c.addItem(st); //System.out.println("c.countItems="+c.countItems()); //System.out.println("Next Element="+b.toString()); } } //updateInput public void updateResults(Choice c){ //removeAll isn't supported by Netscape 3.04 c.removeAll(); Enumeration e = myBuildings.elements(); while (e.hasMoreElements() ){ Building b = (Building) e.nextElement(); c.addItem("Results..."+b.toString()); //System.out.println("Next Element="+b.toString()); } } // //////////////////////////////////////////////////////////////////////// //Code from Robbie // //////////////////////////////////////////////////////////////////////// java.util.Vector buildingVec; // buildings to process (in place) java.awt.Polygon skylinePoly; // skyline (x,y) coords int rmax; // value of largest right side int hmax; // max height // Vector element accessor functions - to save typing Building bVea(int index) { return ((Building) buildingVec.elementAt(index)); } // bVea() void setbVea(Building b, int index) { buildingVec.setElementAt(b,index); // System.out.println("setbVea[" + index + "] = " + b.displaySelf()); return; } // setbVea() void addbVe(Building b) { buildingVec.addElement(b); // System.out.println("addsbVe[" + (buildingVec.size()-1) + "] = " + b.displaySelf()); return; } // addbVe() void emptybV() { buildingVec = new Vector(); return; } // emptybV() void printBV() { Building b; // System.out.println("printBV:"); for (int i = 0; i < buildingVec.size(); i++) { b = bVea(i); // System.out.println("bV[" + i + "] = " + b.toString()); } return; } // printBV() void sortBV() { boolean switched; Building temp; if (buildingVec.size() < 2) { return; } do { switched = false; for (int j=1; j < buildingVec.size(); j++) { if (bVea(j).L < bVea(j-1).L) { temp = bVea(j); setbVea(bVea(j-1),j); setbVea(temp,j-1); switched = true; } else { // check for and remove duplicate buildings if ( bVea(j-1).L == bVea(j).L && bVea(j-1).H == bVea(j).H && bVea(j-1).R == bVea(j).R ) { buildingVec.removeElementAt(j); switched = true; break; } } } } // do while (switched); return; } // sortBV() void mergeAdjacent(int i) { // i is left index in bV of overlapping buildings Building b1,b2; b1 = bVea(i); // skyline building b2 = bVea(i+1); // System.out.println("mergeAdjacent: b1 = " + b1.L + " " + b1.H + " " + b1.R + " bV index =" + i); // System.out.println("mergeAdjacent: b2 = " + b2.L + " " + b2.H + " " + b2.R + " bV index =" + (i+1)); // b1.L <= b2.L if (b1.R < b2.R) { // partial overlap // System.out.println("mergeAdjacent: partial overlap"); if (b1.H < b2.H) { // narrow b1 (old skyline building) setbVea(new Building(b1.L,b1.H,b2.L),i); } else if (b1.H == b2.H) { // join same height buildings setbVea(new Building(b1.L,b1.H,b2.R),i); // get rid of right hand building setbVea(new Building(0,0,0),i+1); } else { // b1.H > b2.H // just narrow b2 setbVea(new Building(b1.R,b2.H,b2.R),i+1); } return; } // b1.R > b2.L and b1.R >= b2.R else { // complete overlap // System.out.println("mergeAdjacent: complete overlap"); if (b1.H <= b2.H) { // split b1 into two // narrow b1 setbVea(new Building(b1.L,b1.H,b2.L),i); // keep the tall "splitter" // add the new building into the bV--for later consideration addbVe(new Building(b2.R,b1.H,b1.R)); } else { // b2 is completely obscured, just keep b1 setbVea(new Building(0,0,0),i+1); } return; } } // mergeBS() void computeSkyline() { boolean overlap_merge; Building b1, b2; int iter = 0; // add a fake zero-height building sortBV(); if (buildingVec.size() > 0) { rmax = bVea(0).R; hmax = bVea(0).H; for (int j=1; j < buildingVec.size(); j++) { if ((bVea(j).R) > rmax) { rmax = bVea(j).R; } if ((bVea(j).H) > hmax) { hmax = bVea(j).H; } } rmax = rmax + 1; hmax = hmax + 1; //System.out.println("rmax = " + rmax); //System.out.println("hmax = " + hmax); addbVe(new Building(0,0,rmax)); } do { overlap_merge = false; iter++; sortBV(); // printBV(); if (buildingVec.size() < 2) { return; } for (int j=1; j < buildingVec.size(); j++) { b1 = bVea(j-1); b2 = bVea(j); // System.out.println("computeSkyline, b1 = " + (j-1) + ": " + b1.displaySelf()); // System.out.println("computeSkyline, b2 = " + j + ": " + b2.displaySelf()); if (b2.L < b1.R) { // overlap mergeAdjacent(j-1); overlap_merge = true; break; } // if (b2.L <= b1.R) } // for (int j=1; j < buildingVec.size(); j++) if (iter > 100) { return; } } while (overlap_merge); printBV(); // now create skylinePoly as a Polygon! skylinePoly = new Polygon(); for (int j=0; j < buildingVec.size(); j++) { skylinePoly.addPoint(bVea(j).L,bVea(j).H); //System.out.println(" j = " + j + " addPoint: (" + bVea(j).L + "," + bVea(j).H + ")"); skylinePoly.addPoint(bVea(j).R,bVea(j).H); //System.out.println(" j = " + j + " addPoint: (" + bVea(j).R + "," + bVea(j).H + ")"); } return; } // computeSkyline() void initBuildingVec() { emptybV(); // empty bV to make applet re-usable! addbVe(new Building(19,18,22)); addbVe(new Building(2,6,7)); addbVe(new Building(1,11,5)); addbVe(new Building(3,13,9)); addbVe(new Building(12,7,16)); addbVe(new Building(14,3,25)); addbVe(new Building(23,13,29)); addbVe(new Building(24,4,28)); } // initBuildingVec() // //////////////////////////////////////////////////////////////////////// //End of code from Robbie // //////////////////////////////////////////////////////////////////////// } //skyline