package gui.simulator; import gui.simulator.facilities.RestRoom; import gui.simulator.facilities.Stage; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Rectangle; import java.awt.Shape; import java.awt.TexturePaint; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.awt.geom.AffineTransform; import java.awt.geom.Area; import java.awt.geom.NoninvertibleTransformException; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.nio.file.Path; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import javax.imageio.ImageIO; import javax.swing.JPanel; import javax.swing.SwingUtilities; public class Terrain extends JPanel { private List entities; private Point2D oldPosition; private Draw dragObject, selectedObject; private BufferedImage background; private Sidebar sidebar; private int festivalheight, festivalwidth; private int sideBarWidth = 200; private int pathgenerate = 1; private WalkingPath currentpath; private SimulatorPane.Terrains terrain; Point2D cameraPoint = new Point2D.Double(festivalwidth/2,festivalheight/2); float cameraScale = 1; private boolean grid; private ArrayList visitors; private ArrayList paths; Point2D lastClickPosition; Point lastMousePosition; Point2D lastMovedMousePosition; public Terrain(int length, int width, SimulatorPane.Terrains terrain){ //get values setFestivalHeight(length); setFestivalWidth(width); grid = true; this.terrain = terrain; visitors = new ArrayList(); paths = new ArrayList(); for(int i=0; i< 40; i++){ visitors.add(new Visitor(new Point(100+(i*15),100))); } //initialize sidebar sidebar = new Sidebar(sideBarWidth, getFestivalHeight(), this); //set terrainbackground switch(terrain){ case BEACH: try { background = ImageIO.read(new File("res/sand.jpg")); } catch (IOException e) { e.printStackTrace(); } break; case GRASS: try { background = ImageIO.read(new File("res/grass.jpg")); } catch (IOException e) { e.printStackTrace(); } break; case URBAN: try { background = ImageIO.read(new File("res/street.jpg")); } catch (IOException e) { e.printStackTrace(); } break; } this.dragObject = null; this.entities = new LinkedList(); this.initEntities(); this.listeners(); } private void getFacility(MouseEvent e){ Point2D clickPoint = getClickPoint(e.getPoint()); if(e.getX() < sideBarWidth) { if(e.getY() < 300){ dragObject = new Stage((int)clickPoint.getX(),(int)clickPoint.getY(), 0.5, 10); }else if(e.getY() > 300 && e.getY() < 550){ dragObject = new RestRoom((int)clickPoint.getX(),(int)clickPoint.getY(), 0.5, 10); }else if(e.getY() > 550 && e.getY() < 800){ dragObject = new AccessPoint(this, (int)clickPoint.getX(),(int)clickPoint.getY(), 0.5, 10); } else if(e.getY() > 800){ dragObject = new ExitPoint(this, (int)clickPoint.getX(),(int)clickPoint.getY(), 0.5, 10); } entities.add(dragObject); } } private void listeners(){ addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { Point2D clickPoint = getClickPoint(e.getPoint()); lastClickPosition = clickPoint; lastMousePosition = e.getPoint(); //if selected in sidebar getFacility(e); //else selected in terrain if(e.getX() > sideBarWidth){ for(Draw drawObject: entities){ if(drawObject.contains(clickPoint)){ if(pathgenerate == 1){ currentpath = new WalkingPath(); currentpath.addPoint(new Point((int)drawObject.getX(), (int)drawObject.getY())); currentpath.setObject1(drawObject); pathgenerate = 2; return; }else if(pathgenerate > 1){ currentpath.addPoint(new Point((int)drawObject.getX(), (int)drawObject.getY())); currentpath.setObject2(drawObject); paths.add(currentpath); pathgenerate = 0; return; }else{ dragObject = drawObject; selectedObject = dragObject; oldPosition = new Point2D.Double(selectedObject.getX(), selectedObject.getY()); return; } } } if(pathgenerate > 1){ currentpath.addPoint(new Point((int)getClickPoint(e.getPoint()).getX(), (int)getClickPoint(e.getPoint()).getY())); } } repaint(); } @Override public void mouseReleased(MouseEvent e) { if(selectedObject != null){ for(Draw drawObject: entities){ if(drawObject == selectedObject){ continue; } if(intersection(selectedObject, drawObject)){ //move back selectedObject.setX(oldPosition.getX()); selectedObject.setY(oldPosition.getY()); } } } selectedObject = null; dragObject = null; repaint(); } }); addMouseMotionListener(new MouseMotionAdapter() { public void mouseMoved(MouseEvent e){ lastMovedMousePosition = getClickPoint(e.getPoint()); } @Override public void mouseDragged(MouseEvent e) { Point2D clickPoint = getClickPoint(e.getPoint()); if(dragObject != null){ if(SwingUtilities.isLeftMouseButton(e)){ dragObject.setX(dragObject.getX() - (lastClickPosition.getX() - clickPoint.getX())); dragObject.setY(dragObject.getY() - (lastClickPosition.getY() - clickPoint.getY())); }else if(SwingUtilities.isRightMouseButton(e)){ dragObject.rotation += (lastClickPosition.getX() - clickPoint.getX() + lastClickPosition.getY() - clickPoint.getY()); } } else { cameraPoint = new Point2D.Double( cameraPoint.getX() + (lastMousePosition.getX() - e.getX()), cameraPoint.getY() + (lastMousePosition.getY() - e.getY()) ); } repaint(); lastMousePosition = e.getPoint(); lastClickPosition = clickPoint; } }); addMouseWheelListener(new MouseWheelListener() { @Override public void mouseWheelMoved(MouseWheelEvent e) { Point2D clickPoint = getClickPoint(e.getPoint()); for(Draw object: entities){ //if object selected, scale object if(object.contains(clickPoint)){ object.scale *= 1 + (e.getPreciseWheelRotation()/10.0); repaint(); return; } } //scale camera cameraScale *= 1 - (e.getPreciseWheelRotation()/10.0); repaint(); } }); } /* * Add facilities on initializing */ private void initEntities(){ //this.entities.add(new Stage(300, 10, 0.5, 10)); //this.entities.add(new Stage(400, 40, 2, 10)); } @Override public void paint(Graphics g) { super.paint(g); Graphics2D g2 = (Graphics2D) g; sidebar.draw(g2); //draw simulation field g2.setClip(new Rectangle2D.Double(sideBarWidth, 0, getWidth()-sideBarWidth, getHeight())); AffineTransform oldTransform = g2.getTransform(); g2.translate(sideBarWidth,0); g2.setTransform(getCamera()); TexturePaint p = new TexturePaint(background, new Rectangle2D.Double(0, 0, 200, 200)); g2.setPaint(p); g2.fill(new Rectangle2D.Double(0,0,festivalwidth,festivalheight)); if(grid){ g2.setColor(new Color(160,160,160,120)); g2.setStroke(new BasicStroke(1)); for(int i = 0; i < (getFestivalWidth()/10)+1; i++){ g2.drawLine(i*10, 0, i*10, getFestivalHeight()); }; for(int i = 0; i < (getFestivalHeight()/10)+1; i++){ g2.drawLine(0, i*10, getFestivalWidth(), i*10); }; } for(Visitor v:visitors){ v.paint(g2); } for(Draw drawObject: entities){ drawObject.draw(g2); if(pathgenerate > 0){ g2.fill(drawObject.getAffineTransform().createTransformedShape(new Rectangle((int)(drawObject.getX()-(drawObject.getWidth()/2)-10),(int)(drawObject.getY()-(drawObject.getHeight()/2)-10), 20, 20))); } } if(pathgenerate > 1){ g2.setStroke(new BasicStroke(10)); currentpath.paint(g2); g2.drawLine((int)currentpath.get(currentpath.getPath().size()-1).getX(),(int)currentpath.get(currentpath.getPath().size()-1).getY(), (int)lastMovedMousePosition.getX(), (int)lastMovedMousePosition.getY()); }else{ for(WalkingPath path:paths){ path.paint(g2); } } //draw collide boxes if(this.selectedObject != null){ Shape shape = this.selectedObject.getRect(); g2.setColor(Color.RED); g2.draw(this.selectedObject.getAffineTransform().createTransformedShape(shape)); boolean collide = false; for(Draw draw: entities){ if(!draw.equals(this.selectedObject)){ if(intersection(this.selectedObject, draw)){ collide = true; } } } if(collide){ g2.setColor(new Color(254, 0, 0, 128)); }else{ g2.setColor(new Color(0, 254, 0, 128)); } g2.fill(this.selectedObject.getAffineTransform().createTransformedShape(this.selectedObject.getRect())); g2.setClip(null); g2.setTransform(oldTransform); } } private Rectangle drawDragRectangle(Draw shape){ Rectangle rectangle = null; rectangle = new Rectangle((int) (shape.getX() - shape.getDistanceToOtherObjects()), (int) (shape.getY() - shape.getDistanceToOtherObjects()), (int) (shape.getWidth() * shape.getScale() + (2 * shape.getDistanceToOtherObjects())), (int) (shape.getHeight() * shape.getScale() + (2 * shape.getDistanceToOtherObjects()))); return rectangle; } private boolean intersection(Draw d1, Draw d2){ Area area = new Area(d1.getAffineTransform().createTransformedShape(d1.getRect())); Area area2 = new Area(d2.getAffineTransform().createTransformedShape(d2.getRect())); area.intersect(area2); return !area.isEmpty(); } public Point2D getClickPoint(Point point) { try { return getCamera().inverseTransform(point, null); } catch (NoninvertibleTransformException e1) { e1.printStackTrace(); } return null; } private AffineTransform getCamera() { AffineTransform tx = new AffineTransform(); tx.translate(-cameraPoint.getX() + getWidth()/2, -cameraPoint.getY() + getHeight()/2); tx.scale(cameraScale, cameraScale); return tx; } public void calculate(){ for(Visitor v:visitors){ v.update(visitors); } for(WalkingPath p:paths){ p.reCalculate(); } } public void setFestivalHeight(int height){ this.festivalheight = height; } public void setFestivalWidth(int width){ this.festivalwidth = width; } public int getFestivalHeight(){ return festivalheight; } public int getFestivalWidth(){ return festivalwidth; } //getters and setters for sidebar public void setDragObject(Draw dragObject){ this.dragObject = dragObject; } public Draw getDragObject(){ return dragObject; } public void addEntity(Draw dragObject){ entities.add(dragObject); } }