package ui.view; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.geom.CubicCurve2D; import java.awt.geom.GeneralPath; import java.awt.geom.Line2D; import java.util.ArrayList; import java.util.LinkedList; import java.awt.Point; import javax.swing.JPanel; import com.sun.org.apache.xerces.internal.util.SynchronizedSymbolTable; import classes.HolonElement; import ui.controller.Control; import ui.model.Model; import classes.HolonSwitch; import java.awt.Cursor; class UnitGraph extends JPanel implements MouseListener, MouseMotionListener, ComponentListener { private static final long serialVersionUID = 1L; private float MAXIMUM = 0; private Point recSize = new Point(8, 8); // Point Size private Graphics2D g2; private CubicCurve2D c = new CubicCurve2D.Double(); private CubicCurve2D cr = new CubicCurve2D.Double(); private CubicCurve2D cl = new CubicCurve2D.Double(); private LinkedList pointList; private double scaleX; private double scaleY; private float[] arrayOfFloats = null; private boolean[] arrayOfBooleans = null; private double width = -1; private double height = -1; private boolean isElement = false; private boolean isSwitch = false; private ArrayList tempElements = new ArrayList<>(); private HolonSwitch tempSwitch; private Model model; private Control controller; private Line2D.Double line = null; GeneralPath graphCurve = new GeneralPath(); private boolean pointDrag = false; private boolean init = true; private Point tempP = null; private double x = 0, y = 0; private int x1, x2, y1, y2, ctrlx1, ctrly1, ctrlx2, ctrly2; public UnitGraph(final Model model, Control control) { setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); this.controller = control; this.model = model; this.pointList = new LinkedList<>(); this.setBackground(Color.WHITE); this.addMouseListener(this); this.addMouseMotionListener(this); this.addComponentListener(this); } /** * Paints all Components on the Canvas * * @param Graphics * */ public void paintComponent(Graphics g) { super.paintComponent(g); g2 = (Graphics2D) g; RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setRenderingHints(rh); g2.setStroke(new BasicStroke(0)); graphCurve.reset(); // Draw the Vertical Lines g2.setColor(Color.BLACK); for (int i = 0; i <= this.getWidth(); i += 10) { g2.drawLine(i, 0, i, this.getHeight()); } for (int i = 0; i <= this.getHeight(); i += 5) { g2.drawLine(0, i, this.getWidth(), i); } if (isElement) { // array fillen fillArrayofValue(); if (arrayOfFloats != null) { // Draw the Lines g2.setStroke(new BasicStroke(2)); g2.setColor(Color.BLACK); for (int i = 0; i < pointList.size() - 1; i++) { c = buildCurve(pointList.get(i), pointList.get(i + 1)); graphCurve.append(c, true); } g2.draw(graphCurve); // Draw the Points g2.setColor(Color.BLUE); for (int i = 0; i < pointList.size() - 0; i++) { g2.fillOval((int) (pointList.get(i).getX() * scaleX - recSize.getX() / 2), (int) (pointList.get(i).getY() * scaleY - recSize.getY() / 2), (int) recSize.getX(), (int) recSize.getY()); } // Iteration Value if (arrayOfFloats != null) { g2.drawString("" + arrayOfFloats[model.getCurIteration()], (model.getCurIteration()) * this.getWidth() / (model.getIterations() - 1) + 2, this.getHeight() - 10); } } /* * // Actual Iteration Point Visualization g2.setColor(Color.RED); * if (arrayOfValue != null) { for (int i = 0; i < * arrayOfValue.length; i++) { g2.fillOval((int) (i * width / * (model.getIterations() - 1) * scaleX - recSize.getX() / 2), (int) * (convertToCanvasY((int) arrayOfValue[i]) * scaleY - * recSize.getY() / 2), (int) recSize.getX(), (int) recSize.getY()); * } } */ } else if (isSwitch) { if (arrayOfBooleans != null) { // array fillen fillArrayofBooleans(); // Draw the Lines g2.setStroke(new BasicStroke(2)); g2.setColor(Color.BLACK); for (int i = 0; i < pointList.size() - 1; i++) { line = new Line2D.Double(pointList.get(i).getX() * scaleX, pointList.get(i).getY() * scaleY, pointList.get(i + 1).getX() * scaleX, pointList.get(i + 1).getY() * scaleY); graphCurve.append(line, true); } g2.draw(graphCurve); /* * // Draw the Points g2.setColor(Color.BLUE); for (int i = 0; i * < pointList.size() - 0; i++) { g2.fillOval((int) * (pointList.get(i).getX() * scaleX - recSize.getX() / 2), * (int) (pointList.get(i).getY() * scaleY - recSize.getY() / * 2), (int) recSize.getX(), (int) recSize.getY()); } */ // Iteration Value if (arrayOfBooleans != null) { g2.drawString("" + arrayOfBooleans[model.getCurIteration()], (model.getCurIteration()) * this.getWidth() / (model.getIterations() - 1) + 2, this.getHeight() - 10); } } } // Iteration Line g2.setColor(Color.BLUE); g2.setStroke(new BasicStroke(1)); g2.drawLine((model.getCurIteration()) * this.getWidth() / (model.getIterations() - 1), 0, (model.getCurIteration()) * this.getWidth() / (model.getIterations() - 1), this.getHeight()); // algorithmus controller.calculateStateForTimeStep(model.getCurIteration()); } @Override public void mouseDragged(MouseEvent e) { if (isElement) { elementDragged(e); } else if (isSwitch) { switchDragged(e); } } /** * Wenn ein Punkt bei einem HolonElement gedragged wird * * @param e */ public void elementDragged(MouseEvent e) { if (pointDrag && tempP != null) { // Out of Bounds verhindern int i = pointList.indexOf(tempP); x = e.getX() / scaleX; y = e.getY() / scaleY; // y if (e.getY() <= 0) { y = 0 / scaleY; } else if (this.getHeight() <= e.getY()) { y = this.getHeight() / scaleY; } // x if (tempP == pointList.getFirst() || tempP == pointList.getLast() || pointList.get(i + 1).getX() <= x || pointList.get(i - 1).getX() >= x) { x = tempP.getX(); } tempP.setLocation(x, y); repaint(); } } /** * Wenn ein Punkt bei einem CpsSwitch gedragged wird * * @param e */ public void switchDragged(MouseEvent e) { if (pointDrag && tempP != null && tempP != pointList.getFirst() && tempP != pointList.getLast()) { int i = pointList.indexOf(tempP); x = e.getX() / scaleX; if (pointList.get(i + 1).getY() == tempP.getY()) { // x if (pointList.get(i + 1).getX() <= x + 1 || pointList.get(i - 2).getX() >= x - 1) { x = tempP.getX(); } pointList.get(i - 1).setLocation(x, pointList.get(i - 1).getY()); } else { // x if (pointList.get(i + 2).getX() <= x + 1 || pointList.get(i - 1).getX() >= x - 1) { x = tempP.getX(); } pointList.get(i + 1).setLocation(x, pointList.get(i + 1).getY()); } tempP.setLocation(x, tempP.getY()); repaint(); } } @Override public void mouseMoved(MouseEvent e) { } @Override public void mouseClicked(MouseEvent e) { } @Override public void mouseEntered(MouseEvent e) { } @Override public void mouseExited(MouseEvent e) { } @Override public void mousePressed(MouseEvent e) { if (isElement) { elementPressed(e); } else if (isSwitch) { switchPressed(e); } } /** * Wenn ein Punkt von einem Element gedrueckt wird * * @param e */ public void elementPressed(MouseEvent e) { boolean added = false; boolean deletePoint = false; double x = e.getX() / scaleX; double y = e.getY() / scaleY; // Click on Point tempP = null; if (pointList != null) { // look if a point was clicked for (Point p : pointList) { if (x >= p.getX() - recSize.getX() / 2 && y >= p.getY() - recSize.getY() / 2 && x <= p.getX() + recSize.getX() / 2 && y <= p.getY() * scaleY + recSize.getY() / 2) { if (e.getButton() == MouseEvent.BUTTON3) { tempP = p; deletePoint = true; } else { pointDrag = true; tempP = p; } } } // New Point if (!pointDrag && e.getButton() != MouseEvent.BUTTON3 && e.getX() != 0 && e.getX() != this.getWidth() / scaleX) { for (int i = 0; i < pointList.size(); i++) { if (x < pointList.get(i).getX() && !added) { if (e.getY() <= 0) { pointList.add(i, new Point((int) (x), (int) (0 / scaleY))); } else { pointList.add(i, new Point((int) (x), (int) y)); } added = true; pointDrag = true; tempP = pointList.get(i); } } } // Delete a Point if (deletePoint && tempP.getX() != 0 && (tempP.getX() != this.getWidth() / scaleX || tempP != pointList.getLast())) { pointList.remove(tempP); } repaint(); } } /** * Wenn ein Punkt von einem Switch gedr�ck wird * * @param e */ public void switchPressed(MouseEvent e) { boolean added = false; boolean deletePoint = false; double x = e.getX() / scaleX; double y = e.getY() / scaleY; // Halbe Iterations Distanz double dist = (width / (model.getIterations() - 1)) / 2; // Click on Point tempP = null; if (pointList != null) { for (Point p : pointList) { if (x >= p.getX() - dist * 2 && x <= p.getX() + dist * 2) { if (e.getButton() == MouseEvent.BUTTON3) { tempP = p; deletePoint = true; } else { pointDrag = true; tempP = p; } } } // New Point if (!pointDrag && e.getButton() != MouseEvent.BUTTON3 && x != 0 && x != width) { for (int i = 0; i < pointList.size() && !added; i++) { if (x < pointList.get(i).getX() - dist) { // double p1, p2 um location der points zu bestimmen double p1 = pointList.get(i - 1).getX(); double p2 = pointList.get(i).getX(); // Punkte hinzufügen, je nachdem ob true oder false if (pointList.get(i - 1).getY() != 0 && pointList.get(i).getY() != 0) { pointList.add(i, new Point((int) ((x + p2) / 2 + dist), (int) height - 1)); pointList.add(i, new Point((int) ((x + p2) / 2 + dist), 0)); pointList.add(i, new Point((int) ((x + p1) / 2 - dist), 0)); pointList.add(i, new Point((int) ((x + p1) / 2 - dist), (int) height - 1)); added = true; } else if (pointList.get(i - 1).getY() == 0 && pointList.get(i).getY() == 0) { pointList.add(i, new Point((int) ((x + p2) / 2 + dist), 0)); pointList.add(i, new Point((int) ((x + p2) / 2 + dist), (int) height - 1)); pointList.add(i, new Point((int) ((x + p1) / 2 - dist), (int) height - 1)); pointList.add(i, new Point((int) ((x + p1) / 2 - dist), 0)); added = true; } } } } // Delete a Point if (deletePoint && tempP.getX() != 0 && (tempP.getX() != this.getWidth() / scaleX || tempP != pointList.getLast())) { int i = pointList.indexOf(tempP); if (tempP.getY() == 0) { pointList.remove(i); pointList.remove(i - 1); pointList.remove(i - 2); pointList.remove(i - 3); } if (tempP.getY() == height - 1) { pointList.remove(i + 2); pointList.remove(i + 1); pointList.remove(i); pointList.remove(i - 1); } } repaint(); } // TODO Siwtch pressed zeugs hier hin } @Override public void mouseReleased(MouseEvent e) { if (pointDrag) { pointDrag = false; tempP = null; } } public void componentResized(ComponentEvent e) { // Wenn ein anderes Element genommen wird if (init) { init = false; // for scale on the first initialisation if (width == -1 && height == -1) { width = this.getWidth(); height = this.getHeight(); } scaleX = this.getWidth() / width; scaleY = this.getHeight() / height; } // Scale scaleX = this.getWidth() / width; scaleY = this.getHeight() / height; repaint(); } @Override public void componentHidden(ComponentEvent e) { } @Override public void componentMoved(ComponentEvent e) { } @Override public void componentShown(ComponentEvent e) { } /* * Emptys the Graph */ public void empty() { pointList = null; tempElements = null; tempSwitch = null; arrayOfFloats = null; arrayOfBooleans = null; isSwitch = false; isElement = false; repaint(); } /* * Resets the Points for the Element */ public void reset() { pointList.removeAll(pointList); pointList.addFirst(new Point(0, 0)); pointList.addLast(new Point((int) (this.getWidth() / scaleX), 0)); repaint(); } /** * converts the number to fit the canvas * * @param double * d, the number to convert * @return the converted number */ public double convertToCanvasY(float d) { return (height - (d * (height / MAXIMUM))); } /** * converts the number to fit the value * * @param double * d, the number to convert * @return the converted number */ public float convertToValueY(double d) { return (float) Math.round(((height - (height * (d / height))) / (height / MAXIMUM)) * 10) / 10; } /** * Visualize the HolonElement on the Graph * * @param HolonElement * ele, which should be visualized */ public void repaintWithNewElement(ArrayList selectedElement) { arrayOfFloats = selectedElement.get(selectedElement.size() - 1).getEnergyAt(); tempElements = selectedElement; pointList = selectedElement.get(selectedElement.size() - 1).getGraphPoints(); isSwitch = false; isElement = true; MAXIMUM = selectedElement.get(selectedElement.size() - 1).getEnergy(); // First time clicked on the Element if (pointList.isEmpty()) { pointList.addFirst(new Point(0, 0)); pointList.addLast(new Point((int) (this.getWidth() / scaleX), 0)); } repaint(); } /** * Visualize the HolonElement on the Graph * * @param HolonElement * ele, which should be visualized */ public void repaintWithNewSwitch(HolonSwitch s) { arrayOfBooleans = s.getActiveAt(); tempSwitch = s; pointList = s.getGraphPoints(); isSwitch = true; isElement = false; // First time clicked on the Element if (pointList.isEmpty()) { pointList.addFirst(new Point(0, 0)); pointList.addLast(new Point((int) (width), 0)); } repaint(); } /** * Build a Curve for the Graph * * @param Point,Point * ,startpoint p1 and endpoint p2 * * @return CubicCurve2D, c, the CubicCurve2D for the Graph */ public CubicCurve2D buildCurve(Point p1, Point p2) { x1 = (int) p1.getX(); y1 = (int) p1.getY(); x2 = (int) p2.getX(); y2 = (int) p2.getY(); // calculate the controllpoints ctrlx1 = (int) p1.getX() + ((int) p2.getX() - (int) p1.getX()) / 2; ctrlx2 = (int) p2.getX() - ((int) p2.getX() - (int) p1.getX()) / 2; if (y1 < y2) { ctrly1 = (int) p1.getY() + ((int) p2.getY() - (int) p1.getY()) / 10; ctrly2 = (int) p2.getY() - ((int) p2.getY() - (int) p1.getY()) / 10; } else { ctrly1 = (int) p1.getY() - ((int) p1.getY() - (int) p2.getY()) / 10; ctrly2 = (int) p2.getY() + ((int) p1.getY() - (int) p2.getY()) / 10; } // set the curve c.setCurve(x1 * scaleX, y1 * scaleY, ctrlx1 * scaleX, ctrly1 * scaleY, ctrlx2 * scaleX, ctrly2 * scaleY, x2 * scaleX, y2 * scaleY); return c; } /** * Fills the Arrays with booleans */ public void fillArrayofBooleans() { for (int i = 0; i < arrayOfBooleans.length; i++) { int t = (int) getYValueAt_2((int) (i * width / (model.getIterations() - 1))); if (t == 0) { arrayOfBooleans[i] = true; } else { arrayOfBooleans[i] = false; } } } /** * Fills the Arrays of each HolonElement */ @SuppressWarnings("unchecked") public void fillArrayofValue() { for (HolonElement he : tempElements) { MAXIMUM = he.getEnergy(); he.setGraphPoints((LinkedList) pointList.clone()); for (int i = 0; i < arrayOfFloats.length; i++) { he.getEnergyAt()[i] = convertToValueY(getYValueAt_2((int) (i * width / (model.getIterations() - 1)))); } arrayOfFloats = he.getEnergyAt(); } } /** * * @param xVal, * the x value for the y value * @return y, the value at x */ public float getYValueAt(int xVal) { for (int i = 0; i < pointList.size() - 1; i++) { // get the Points if (xVal <= pointList.get(i + 1).getX()) { // Curve erstellen Line2D l1 = new Line2D.Double(pointList.get(i).getX(), pointList.get(i).getY(), pointList.get(i + 1).getX(), pointList.get(i + 1).getY()); Line2D l2 = new Line2D.Double(xVal, 0, xVal, height); return getIntersectionPoint(l1, l2); } } return 0; } /** * * @param xVal, * the x value for the y value * @return y, the value at x */ public float getYValueAt_2(int xVal) { for (int i = 0; i < pointList.size() - 1; i++) { // get the Points if (xVal >= pointList.get(i).getX()) { // Curve erstellen c = buildCurve(pointList.get(i), pointList.get(i + 1)); c.subdivide(cl, cr); // Teil der Kurve aussuchen if (cl.getX1() <= xVal * scaleX && cl.getX2() > xVal * scaleX) { c = cl; // Kurve Links von "unten" if (pointList.get(i).getY() >= pointList.get(i + 1).getY()) { for (float j = (float) (height - 1); j >= 0; j -= 0.1f) { if (c.contains(xVal * scaleX, j * scaleY)) { return (float) (j); } } } else {// Kurve Links von "oben" for (float j = 0; j < height; j += 0.1f) { if (c.contains(xVal * scaleX, j * scaleY)) { return (float) (j); } } } } else { c = cr; // Kurve Links von "unten" if (pointList.get(i).getY() >= pointList.get(i + 1).getY()) { for (float j = 0; j < height; j += 0.1f) { if (c.contains(xVal * scaleX, j * scaleY)) { return (float) (j); } } } else {// Kurve Links von "oben" for (float j = (float) (height - 1); j >= 0; j -= 0.1f) { if (c.contains(xVal * scaleX, j * scaleY)) { return (float) (j); } } } } } } return getYValueAt(xVal); } /** * * @param l1, * the first Line * @param l2, * the second Line * * @return The Intersection Point */ public float getIntersectionPoint(Line2D l1, Line2D l2) { if (!l1.intersectsLine(l2)) { return 0;// null; } double px = l1.getX1(), py = l1.getY1(), rx = l1.getX2() - px, ry = l1.getY2() - py; double qx = l2.getX1(), qy = l2.getY1(), sx = l2.getX2() - qx, sy = l2.getY2() - qy; double det = sx * ry - sy * rx; if (det == 0) { return 0;// null; } else { double z = (sx * (qy - py) + sy * (px - qx)) / det; if (z < 0 || z > 1) { return 0;// new Point(0, 0); // intersection at end point! } return (float) (py + z * ry);// new Point((int) (px + z * rx), (int) // (py + z * ry)); } } // end intersection line-line }