package de.wwwu.awolf.view.panels; import de.wwwu.awolf.model.Line; import de.wwwu.awolf.model.Point; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.ValueAxis; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; import org.jfree.data.time.DateRange; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; import org.jfree.util.ShapeUtilities; import javax.swing.*; import java.awt.*; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.util.LinkedList; import java.util.List; /** * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. * * @Author: Armin Wolf * @Email: a_wolf28@uni-muenster.de * @Date: 28.05.2017. */ public class DualityPanel extends JPanel { private List lines; private List points; private JFreeChart chart; private ChartPanel panel; private XYSeriesCollection dataset; private JScrollPane scrollPane; private double domainMin, domainMax; private double rangeMin, rangeMax; private ValueAxis domain; private ValueAxis range; private Double delta = 1d; private Boolean ctrlPressed = false; private Boolean shiftPressed = false; /** * Konstruktor */ public DualityPanel() { super(); this.setPreferredSize(new Dimension(800, 800)); this.setMinimumSize(new Dimension(800, 800)); this.setLayout(new BorderLayout()); } /** * Hilfsmethode um die Parameter im einem Schritt zu setzen * * @param lines Liste der Geraden * @param points Liste der Schnittpunkte * @param xmin minimale x-Koordinate * @param xmax maximale x-Koordinate * @param ymin minimale y-Koordinate * @param ymax maximale y-Koordinate */ public void setPrameters(List lines, List points, Double xmin, Double xmax, Double ymin, Double ymax) { this.lines = new LinkedList<>(lines); this.points = new LinkedList<>(points); this.domainMin = xmin; this.domainMax = xmax; this.rangeMin = ymin; this.rangeMax = ymax; } /** * Die Methode erzeugt ein Arrangement von Geraden. */ public void createArrangement() { dataset = new XYSeriesCollection(); for (Line p : lines) { XYSeries series = new XYSeries(p.getId() + "#" + p.getX1() + "---" + p.getY1()); series.add(p.getX1(), p.getY1()); series.add(p.getX2(), p.getY2()); dataset.addSeries(series); } XYSeries intersections = new XYSeries("intersections"); for (Point p : points) { intersections.add(p.getX(), p.getY()); } dataset.addSeries(intersections); chart = ChartFactory.createXYLineChart(null, null, null, dataset, PlotOrientation.HORIZONTAL, false, false, false); chart.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)); chart.setAntiAlias(true); final XYPlot plot = chart.getXYPlot(); domain = plot.getDomainAxis(); range = plot.getRangeAxis(); domain.setRange(domainMin - 1, domainMax + 1); range.setRange(rangeMin - 1, rangeMax + 1); plot.setBackgroundPaint(Color.WHITE); plot.setDomainGridlinePaint(Color.white); plot.setRangeGridlinePaint(Color.white); final XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer(); renderer.setSeriesLinesVisible(dataset.indexOf(intersections), false); plot.setRenderer(renderer); for (int i = 0; i < lines.size(); i++) { // Setze die Shapes für die Schnittpunkte renderer.setSeriesPaint(i, Color.BLUE); renderer.setBaseSeriesVisible(true); } Shape shape = ShapeUtilities.createDiagonalCross(4, 1); renderer.setSeriesPaint(lines.size(), Color.BLACK); renderer.setSeriesShape(lines.size(), shape); panel = new ChartPanel(chart); panel.setPreferredSize(new Dimension(800, 800)); addKeyListener(this); addZooming(panel); this.setFocusable(true); JTextArea info = new JTextArea(); info.setWrapStyleWord(true); info.setLineWrap(true); info.setAlignmentX(JTextArea.CENTER_ALIGNMENT); info.setText("Um in dem Plot hineinzuzoomen kann das Mausrad verwendett werden. Um sich anschließen vertikal bzw. horizontal zu bewegen kann die Kombination (Umschalt/Steuerung) und Mausrad verwendett werden."); Font font = new Font("Serif", Font.ITALIC, 14); info.setFont(font); //info.setForeground(Color.DARK_GRAY); info.setEditable(false); info.setWrapStyleWord(true); this.add(info, BorderLayout.SOUTH); this.add(panel, BorderLayout.CENTER); } /** * Hilfmethode für die Zoom-Funktion im Panel * * @param component Komponente */ public void addKeyListener(JComponent component) { component.addKeyListener(new KeyListener() { @Override public void keyReleased(KeyEvent e) { ctrlPressed = false; shiftPressed = false; } @Override public void keyTyped(KeyEvent e) { } @Override public void keyPressed(KeyEvent e) { if (e.isControlDown()) { ctrlPressed = true; } if (e.isShiftDown()) { shiftPressed = true; } } }); } /** * Zoom-Funktionalität für das Panel * * @param chartPanel */ protected void addZooming(ChartPanel chartPanel) { chartPanel.addMouseWheelListener(new MouseWheelListener() { @Override public void mouseWheelMoved(MouseWheelEvent e) { double min; double max; Double val; val = e.getPreciseWheelRotation() * -1; if (ctrlPressed) { //Logging.logInfo("CTRL + ZOOM"); min = range.getLowerBound(); max = range.getUpperBound(); DateRange dateRangeX = move(val, min, max); range.setRange(dateRangeX); } else if (shiftPressed) { //Logging.logInfo("SHIFT + ZOOM"); min = domain.getLowerBound(); max = domain.getUpperBound(); DateRange dateRangeY = move(val, min, max); domain.setRange(dateRangeY); } else { Double x = (double) e.getY(); Double y = (double) e.getY(); if (e.getScrollType() != MouseWheelEvent.WHEEL_UNIT_SCROLL) return; if (e.getWheelRotation() < 0) increaseZoom((ChartPanel) e.getComponent()); else decreaseZoom((ChartPanel) e.getComponent()); } } /** * Bewegung im Panel * @param val Bewegung * @param min minimale Wert * @param max maximale Wert * @return aktuell Sichtbare Teil des Panels */ private DateRange move(Double val, Double min, Double max) { Double minimum = min; Double maximum = max; delta = Math.abs(maximum - minimum) * 0.01 * val; minimum = minimum + delta; maximum = maximum + delta; return new DateRange(minimum, maximum); } /** * Reinzoomen * @param chart chart */ public synchronized void increaseZoom(JComponent chart) { ChartPanel ch = (ChartPanel) chart; zoomChartAxis(ch, true); } /** * Rauszoomen * @param chart chart */ public synchronized void decreaseZoom(JComponent chart) { ChartPanel ch = (ChartPanel) chart; zoomChartAxis(ch, false); } /** * Zoom * @param chartP * @param increase */ private void zoomChartAxis(ChartPanel chartP, boolean increase) { int width = chartP.getMaximumDrawWidth() - chartP.getMinimumDrawWidth(); int height = chartP.getMaximumDrawHeight() - chartP.getMinimumDrawWidth(); if (increase) { chartP.zoomInBoth(width * 0.5, height * 0.5); } else { chartP.zoomOutBoth(width * 0.5, height * 0.5); } } }); } /** * Datensatz leeren */ public void clear() { if (dataset != null) dataset.removeAllSeries(); } }