import java.awt.Color; import java.util.ArrayList; import java.util.Scanner; /*** DUMMY IMAGE VIEWER FOR THE JUDGE ***/ /*** DO NOT CHANGE THIS CODE ***/ /*** COMMENT OUT THE FOLLOWING LINE TO USE THE REAL IMAGEVIEWER ***/ //import visual.ImageViewer; /*** COMMENT THIS CLASS TO USE THE REAL IMAGEVIEWER ***/ class ImageViewer { // the following helper class is required for book-keeping of draw operations, // in order to create uniqueness of the representation // for the judge class Element{ Element next; boolean ellipse; int x1,y1,x2,y2; Color c; Element (boolean E, int X1, int Y1, int X2, int Y2, Color C){ ellipse = E; x1 = X1; y1 = Y1; x2 = X2; y2= Y2; // unique ordering of line direction if (!ellipse && (x1 > x2 || x1 == x2 && y1 > y2)){ int t = x1; x1 = x2; x2 = t; t = y1; y1 = y2; y2 = t; } c = C; } void out(){ if (ellipse) System.out.println(getString(c)+" ellipse at ("+x1+","+y1+") with radiusx: "+ x2+" and radiusy: "+y2); else System.out.println(getString(c)+" line from ("+x1+","+y1+") to ("+x2+","+y2+")"); } // order on figures in order to create unique output on the judge boolean SmallerThan(Element than){ if (ellipse & !than.ellipse) return true; else if (!ellipse & than.ellipse) return false; else{ if (x1 < than.x1) return true; if (x1 > than.x1) return false; // now x1 == than.x1 if (y1 < than.y1) return true; if (y1 > than.y1) return false; // now y1 == than.y1 if (x2 < than.x2) return true; if (x2 > than.x2) return false; // now x2 == than.x2 if (y2 < than.y2) return true; if (y2 > than.y2) return false; // now y2 == than.y2 return false; } } } // list of elements "drawn" on this viewer Element first; // add Element to list of elements in a sorted fashion void AddElement(boolean ellipse, int x1,int y1,int x2,int y2,Color c){ Element e = new Element(ellipse,x1,y1,x2,y2,c); if (first == null || e.SmallerThan(first)){ e.next = first; first = e;} else { Element prev = first; while (prev.next != null && !e.SmallerThan(prev.next)) prev = prev.next; e.next = prev.next; prev.next = e; } } public ImageViewer(int w, int h) { } // register line draw operation in list above void line(int x1, int y1, int x2, int y2, Color c) { AddElement(false,x1,y1,x2,y2,c); } // register ellipse draw operation in list above void ellipse(int px, int py, int radiusx, int radiusy, Color c) { AddElement(true,px,py,radiusx,radiusy,c); } // we "draw" really only when update is called with guaranteed order // for the judge void update() { Element e = first; while (e != null) { e.out(); e = e.next; } } String getString(Color c) { if (c == Color.black) { return "black"; } else if (c == Color.red) { return "red"; } else { return "unknown color"; } } } /*** WORK ON THE CODE BELOW ***/ abstract class Shape { // isPaintable defines if this shape will be painted or not Shape(boolean isPaintable) { this.isPaintable = isPaintable; } // This method sets the coordinates(x,y) of the shape public void setCoordinates(int x, int y) { this.x = x; this.y = y; } // This method return the color of the shape, black for paintable shapes // and red for not-paintable shapes public Color getColor() { if (isPaintable) { return Color.black; } else { return Color.red; } } // Returns area of the shape abstract public double getArea(); // Draws the shape on the ImageViewer abstract public void draw(ImageViewer viewer); // variable to indicate if shape is paintable boolean isPaintable; // coordinates of the shape int x; int y; } class Triangle extends Shape { Triangle(int w, int h, boolean isBack) { super(isBack); width = w; height = h; } @Override public double getArea() { return width * height / 2.0; } @Override public void draw(ImageViewer viewer) { // Top to Left Bottom viewer.line(x, y, x-width/2, y+height, getColor()); // Top to Right Bottom viewer.line(x, y, x+width/2, y+height, getColor()); // Bottom Left to Bottom Right viewer.line(x-width/2, y+height, x+width/2, y+height, getColor()); } private int width; private int height; } class Rectangle extends Shape { Rectangle(int w, int h, boolean isBack) { super(isBack); width = w; height = h; } @Override public double getArea() { return width * height; } @Override public void draw(ImageViewer viewer) { // Bottom Left to Bottom Right viewer.line(x, y+height, x+width, y+height, getColor()); // Bottom Left to Top Left viewer.line(x, y+height, x, y, getColor()); // Bottom Right to Top Right viewer.line(x+width, y+height, x+width, y, getColor()); // Top Left to Top Right viewer.line(x, y, x+width, y, getColor()); } private int width; private int height; } class Ellipse extends Shape { Ellipse(int rx, int ry, boolean isBack) { super(isBack); this.radiusx = rx; this.radiusy = ry; } @Override public double getArea() { return radiusx * radiusy * Math.PI; } @Override public void draw(ImageViewer viewer) { viewer.ellipse(x, y, radiusx, radiusy, getColor()); } private int radiusx; private int radiusy; } class Main { public static void main(String[] args) { ArrayList shapes = new ArrayList(); int px, py; String sign; // Create scanner to read in values Scanner scanner = new Scanner(System.in); while (scanner.hasNext()) { String cmd = scanner.next(); if (cmd.equals("newtriangle")) { // Insert a new triangle // Read in sign sign = scanner.next(); // Read in coordinates px = scanner.nextInt(); py = scanner.nextInt(); // Read in width & height int width = scanner.nextInt(); int height = scanner.nextInt(); shapes.add(new Triangle(width, height, sign.equals("+"))); shapes.get(shapes.size()-1).setCoordinates(px, py); } else if (cmd.equals("newrectangle")) { // Insert a new rectangle // Read in sign sign = scanner.next(); // Read in coordinates px = scanner.nextInt(); py = scanner.nextInt(); // Read in width & height int width = scanner.nextInt(); int height = scanner.nextInt(); shapes.add(new Rectangle(width, height, sign.equals("+"))); shapes.get(shapes.size()-1).setCoordinates(px, py); } else if (cmd.equals("newellipse")) { // Insert a new ellipse // Read in sign sign = scanner.next(); // Read in coordinates px = scanner.nextInt(); py = scanner.nextInt(); // Read in width & height int radiusx = scanner.nextInt(); int radiusy = scanner.nextInt(); shapes.add(new Ellipse(radiusx, radiusy, sign.equals("+"))); shapes.get(shapes.size()-1).setCoordinates(px, py); } else if (cmd.equals("paintarea")) { //Calculate total are to be painted // Iterate through shape list and calculate paint area double area = 0.0; for (Shape s : shapes) { if (s.isPaintable) { area += s.getArea(); } else { area -= s.getArea(); } } System.out.println("Area: "+area); } else if (cmd.equals("drawshapes")) { // Draw all shapes // Create new viewer ImageViewer viewer = new ImageViewer(800,500); // Iterate through shape list and draw all shapes for (Shape s : shapes) { s.draw(viewer); } // Update viewer viewer.update(); } else { System.out.println("Invalid input. terminating..."); break; } //if-else } //while // Close scanner to avoid resource leak scanner.close(); } } /* TEST INPUT: newrectangle + 300 250 300 200 newtriangle + 450 100 300 150 newrectangle - 320 300 75 150 newrectangle - 450 300 40 60 newrectangle - 525 300 40 60 newellipse - 450 200 50 40 paintarea newtriangle + 125 100 50 50 newrectangle - 100 100 50 50 newellipse - 125 125 25 25 drawshapes */ /* TEST OUTPUT: Area: 60166.814692820415 red ellipse at (125,125) with radiusx: 25 and radiusy: 25 red ellipse at (450,200) with radiusx: 50 and radiusy: 40 red line from (100,100) to (100,150) red line from (100,100) to (150,100) black line from (100,150) to (125,100) black line from (100,150) to (150,150) red line from (100,150) to (150,150) black line from (125,100) to (150,150) red line from (150,100) to (150,150) black line from (300,250) to (300,450) black line from (300,250) to (450,100) black line from (300,250) to (600,250) black line from (300,250) to (600,250) black line from (300,450) to (600,450) red line from (320,300) to (320,450) red line from (320,300) to (395,300) red line from (320,450) to (395,450) red line from (395,300) to (395,450) black line from (450,100) to (600,250) red line from (450,300) to (450,360) red line from (450,300) to (490,300) red line from (450,360) to (490,360) red line from (490,300) to (490,360) red line from (525,300) to (525,360) red line from (525,300) to (565,300) red line from (525,360) to (565,360) red line from (565,300) to (565,360) black line from (600,250) to (600,450) */