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.Line2D; import java.util.LinkedList; import java.awt.Point; import javax.swing.JPanel; import classes.HolonElement; import ui.controller.Control; import ui.model.Model; import java.awt.Cursor; class UnitGraph extends JPanel implements MouseListener, MouseMotionListener, ComponentListener { private static final long serialVersionUID = 1L; private int ITERATIONS = 50; private float MAXIMUM = 0; private Point recSize = new Point(8, 8); // Point Size private Graphics2D g2; private CubicCurve2D c = new CubicCurve2D.Double(); private LinkedList pointList; private double scaleX; private double scaleY; private float[] arrayOfValue = null; private double width = -1; private double height = -1; private HolonElement tempElement; private Model model; private Control controller; private boolean pointDrag = false; private boolean init = false; 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.ITERATIONS = model.getIterations(); this.pointList = new LinkedList<>(); 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(1)); if (arrayOfValue != null) { for (int i = 0; i < arrayOfValue.length; i++) { arrayOfValue[i] = convertToValueY(getYValueAt((int) (i * width / (ITERATIONS - 1)))); } } // Draw the Vertical Lines g2.setColor(new Color(240, 240, 240)); for (int i = 0; i < ITERATIONS; i++) { g2.drawLine((i) * this.getWidth() / (ITERATIONS - 1), 0, (i) * this.getWidth() / (ITERATIONS - 1), this.getHeight()); } for (int i = 0; i < ITERATIONS; i++) { g2.drawLine(0, (i) * this.getHeight() / (ITERATIONS - 1), this.getWidth(), (i) * this.getHeight() / (ITERATIONS - 1)); } // Draw the Lines g2.setColor(Color.BLACK); for (int i = 0; i < pointList.size() - 1; i++) { c = buildCurve(pointList.get(i), pointList.get(i + 1)); g2.draw(c); } // 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()); } g2.drawLine((model.getCurIteration()) * this.getWidth() / (ITERATIONS - 1), 0, (model.getCurIteration()) * this.getWidth() / (ITERATIONS - 1), this.getHeight()); //Actual Iteration Point Visualization /* g2.setColor(Color.RED); if (arrayOfValue != null) { for (int i = 0; i < arrayOfValue.length; i++) { g2.fillOval((int) (i * width / (ITERATIONS - 1) * scaleX - recSize.getX() / 2), (int) (convertToCanvasY((int) arrayOfValue[i]) * scaleY - recSize.getY() / 2), (int) recSize.getX(), (int) recSize.getY()); } } */ } @Override public void mouseDragged(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.getX() == 0 || tempP.getX() == this.getWidth() / scaleX || pointList.get(i + 1).getX() <= x || pointList.get(i - 1).getX() >= x) { x = tempP.getX(); } tempP.setLocation(x, y); } repaint(); } @Override public void mouseMoved(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseClicked(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseEntered(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseExited(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mousePressed(MouseEvent e) { boolean added = false; boolean deletePoint = false; double x = e.getX() / scaleX; double y = e.getY() / scaleY; // Click on Point tempP = null; 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; } } } 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); } } } if (deletePoint && tempP.getX() != 0 && (tempP.getX() != this.getWidth() / scaleX || tempP != pointList.getLast())) { pointList.remove(tempP); } repaint(); } @Override public void mouseReleased(MouseEvent e) { if (pointDrag) { pointDrag = false; tempP = null; } } public void componentResized(ComponentEvent e) { if (init) { MAXIMUM = tempElement.getEnergy(); init = false; // for scale if (width == -1 && height == -1) { width = this.getWidth(); height = this.getHeight(); } scaleX = this.getWidth() / width; scaleY = this.getHeight() / height; if (pointList.isEmpty()) { pointList.addFirst(new Point(0, 0)); pointList.addLast(new Point((int) (this.getWidth() / scaleX), 0)); } } 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) { } /* * Resets the Graph */ 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) { System.out.println(""+(height + (d*(height/MAXIMUM)))); 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)((height - ( height * (d/height)))/(height/MAXIMUM)); } /** * Visualize the HolonElement on the Graph * * @param HolonElement * ele, which should be visualized */ public void repaintWithNewElement(HolonElement ele) { arrayOfValue = ele.getEnergyAt(); tempElement = ele; pointList = ele.getGraphPoints(); init = true; componentResized(null); 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(); 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; } c.setCurve(x1 * scaleX, y1 * scaleY, ctrlx1 * scaleX, ctrly1 * scaleY, ctrlx2 * scaleX, ctrly2 * scaleY, x2 * scaleX, y2 * scaleY); return c; } /** * * @param xVal, * the x value for the y value * @return y, the value at x */ public int 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 (int) getIntersectionPoint(l1, l2).getY(); } } return 0; } public Point getIntersectionPoint(Line2D l1, Line2D l2) { if (!l1.intersectsLine(l2)) return 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 null; } else { double z = (sx * (qy - py) + sy * (px - qx)) / det; if (z < 0 || z > 1) return new Point(0,0); // intersection at end point! return new Point((int) (px + z * rx), (int) (py + z * ry)); } } // end intersection line-line }