diff --git a/src/main/java/Model/Arrangement.java b/src/main/java/Model/Arrangement.java index 7d40e44..7e5b4e2 100644 --- a/src/main/java/Model/Arrangement.java +++ b/src/main/java/Model/Arrangement.java @@ -13,6 +13,10 @@ public class Arrangement { private LinkedList nodes; private LinkedList lines; + private Double xMinimum; + private Double xMaximum; + private Double yMinimum; + private Double yMaximum; public Arrangement() { nodes = new LinkedList<>(); @@ -39,5 +43,35 @@ public class Arrangement { this.lines = lines; } + public Double getxMinimum() { + return xMinimum; + } + public void setxMinimum(Double xMinimum) { + this.xMinimum = xMinimum; + } + + public Double getxMaximum() { + return xMaximum; + } + + public void setxMaximum(Double xMaximum) { + this.xMaximum = xMaximum; + } + + public Double getyMinimum() { + return yMinimum; + } + + public void setyMinimum(Double yMinimum) { + this.yMinimum = yMinimum; + } + + public Double getyMaximum() { + return yMaximum; + } + + public void setyMaximum(Double yMaximum) { + this.yMaximum = yMaximum; + } } diff --git a/src/main/java/Presenter/Import/DataImporter.java b/src/main/java/Presenter/Import/DataImporter.java index 6878eef..8ef1b40 100644 --- a/src/main/java/Presenter/Import/DataImporter.java +++ b/src/main/java/Presenter/Import/DataImporter.java @@ -2,6 +2,7 @@ package Presenter.Import; import Model.Arrangement; import Model.Line; +import Presenter.Presenter; import com.opencsv.CSVReader; import java.io.File; import java.io.FileNotFoundException; @@ -26,8 +27,12 @@ public class DataImporter extends Observable{ private CSVReader reader; private Arrangement model; - public DataImporter(File file, Arrangement model) { - this.model = model; + + public DataImporter(File file, Presenter presenter) { + this.model = new Arrangement(); + presenter.setModel(this.model); + + this.file = file; try { diff --git a/src/main/java/Presenter/Presenter.java b/src/main/java/Presenter/Presenter.java index c52d102..9c9c8e5 100644 --- a/src/main/java/Presenter/Presenter.java +++ b/src/main/java/Presenter/Presenter.java @@ -115,28 +115,33 @@ public class Presenter implements Observer { } - public void visualizeDualLines() { view.createArrangement(); } + /*************************************************************************************************************************** * Ausführung der Algorithmen ***************************************************************************************************************************/ public void calculateLMS(String[] input) { - Double constant = Double.parseDouble(input[0]); - Double error = Double.parseDouble(input[1]); - lms = new LeastMedianOfSquaresEstimator(model.getLines(), model.getNodes(), this); - lms.setConstant(constant); - lms.setQuantileError(error); - lms.addObserver(this); - lms.run(); + if (input[0] != null && input[1] != null){ + Double constant = Double.parseDouble(input[0]); + Double error = Double.parseDouble(input[1]); + lms = new LeastMedianOfSquaresEstimator(model.getLines(), model.getNodes(), this); + lms.setConstant(constant); + lms.setQuantileError(error); + lms.addObserver(this); + lms.run(); + } } public void calculateRM(String input){ - RepeatedMedianEstimator rm = new RepeatedMedianEstimator(this.getLines(), this); - rm.setBeta(Double.parseDouble(input)); - rm.addObserver(this); - rm.run(); + if (input != null){ + RepeatedMedianEstimator rm = new RepeatedMedianEstimator(this.getLines(), this); + Double parameter = Double.parseDouble(input); + rm.setBeta(parameter); + rm.addObserver(this); + rm.run(); + } } /*************************************************************************************************************************** @@ -178,15 +183,33 @@ public class Presenter implements Observer { } public void calcArrangementNodes() { + + try { Thread thread = new Thread(() -> { + Double xMinimum = Double.MAX_VALUE; + Double xMaximum = Double.MIN_VALUE; + Double yMinimum = Double.MAX_VALUE; + Double yMaximum = Double.MIN_VALUE; for (int i = 0; i < getLines().size(); i++) { for (int j = i; j < getLines().size(); j++) { if (i != j) { - model.addNode(calcIntersection(getLines().get(j), getLines().get(i))); + Point intersection = calcIntersection(getLines().get(j), getLines().get(i)); + model.addNode(intersection); + if (intersection.getX() != Double.POSITIVE_INFINITY && intersection.getX() != Double.NEGATIVE_INFINITY && + intersection.getY() != Double.POSITIVE_INFINITY && intersection.getY() != Double.NEGATIVE_INFINITY ){ + xMinimum = xMinimum > intersection.getX() ? intersection.getX() : xMinimum; + xMaximum = xMaximum < intersection.getX() ? intersection.getX() : xMaximum; + yMinimum = yMinimum > intersection.getY() ? intersection.getY() : yMinimum; + yMaximum = yMaximum < intersection.getY() ? intersection.getY() : yMaximum; + } } } } + model.setxMinimum(xMinimum); + model.setxMaximum(xMaximum); + model.setyMaximum(yMaximum); + model.setyMinimum(yMinimum); }); thread.start(); thread.join(); @@ -213,7 +236,7 @@ public class Presenter implements Observer { } public void startImport(File file){ - DataImporter importer = new DataImporter(file, getModel()); + DataImporter importer = new DataImporter(file, this); importer.addObserver(this); importer.run(); } diff --git a/src/main/java/View/ArrangementDialog.java b/src/main/java/View/ArrangementDialog.java index e3ee7ce..ea23c57 100644 --- a/src/main/java/View/ArrangementDialog.java +++ b/src/main/java/View/ArrangementDialog.java @@ -1,16 +1,24 @@ package View; +import Model.Arrangement; import Model.Line; import Model.Point; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; +import java.awt.FlowLayout; import java.awt.RenderingHints; import java.awt.Shape; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; import java.util.LinkedList; +import javax.swing.JComponent; import javax.swing.JPanel; import javax.swing.JSlider; import javax.swing.SwingConstants; +import javax.swing.event.MouseInputAdapter; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; @@ -20,6 +28,7 @@ import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; +import org.jfree.ui.RectangleEdge; import org.jfree.util.ShapeUtilities; /** @@ -33,8 +42,6 @@ public class ArrangementDialog extends JPanel { private LinkedList lines; private LinkedList points; - private double max; - private double min; private JFreeChart chart; private ChartPanel panel; private JSlider hslider; @@ -49,24 +56,24 @@ public class ArrangementDialog extends JPanel { this.setPreferredSize(new Dimension(800, 800)); this.setMinimumSize(new Dimension(800, 800)); this.setLayout(new BorderLayout()); - this.vslider = new JSlider(SwingConstants.VERTICAL, 1, 100, 50); - this.hslider = new JSlider(SwingConstants.HORIZONTAL, 10, 1000, 500); + this.vslider = new JSlider(SwingConstants.VERTICAL, 1, 10000, 5000); + this.hslider = new JSlider(SwingConstants.HORIZONTAL, 1, 10000, 5000); } - public void setPrameters(LinkedList lines, LinkedList points) { + public void setPrameters(LinkedList lines, LinkedList points, Double xmin, Double xmax, Double ymin, Double ymax) { this.lines = lines; this.points = points; - this.domainMin = Double.MAX_VALUE; - this.domainMax = Double.MIN_VALUE; - this.rangeMin = Double.MAX_VALUE; - this.rangeMax = Double.MIN_VALUE; + this.domainMin = xmin; + this.domainMax = xmax; + this.rangeMin = ymin; + this.rangeMax = ymax; } public void createArrangement() { XYSeriesCollection dataset = new XYSeriesCollection(); for (Line p : lines) { - XYSeries series = new XYSeries(p.getId()); + 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); @@ -74,26 +81,25 @@ public class ArrangementDialog extends JPanel { XYSeries intersections = new XYSeries("intersections"); for (Point p : points) { - domainMax = domainMax < p.getX() ? p.getX() : domainMax; - domainMin = domainMin > p.getX() ? p.getX() : domainMin; - rangeMax = rangeMax < p.getY() ? p.getY() : rangeMax; - rangeMin = rangeMin > p.getY() ? p.getY() : rangeMin; intersections.add(p.getX(), p.getY()); } + dataset.addSeries(intersections); - chart = ChartFactory.createXYLineChart( - null, null, null, dataset, + chart = ChartFactory.createXYLineChart(null, null, null, dataset, PlotOrientation.HORIZONTAL, false, false, false); - chart.setRenderingHints( - new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)); + + chart.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON)); chart.setAntiAlias(true); - final XYPlot plot = chart.getXYPlot(); + + final XYPlot plot = chart.getXYPlot(); domain = plot.getDomainAxis(); range = plot.getRangeAxis(); + System.out.println(domainMin+" -- "+domainMax+" -- "+rangeMin+" -- "+rangeMax); domain.setRange(domainMin - 1, domainMax + 1); range.setRange(rangeMin - 1, rangeMax + 1); plot.setBackgroundPaint(Color.WHITE); @@ -118,6 +124,7 @@ public class ArrangementDialog extends JPanel { panel.setPreferredSize(new Dimension(800, 800)); addListener(); + addZooming(panel); this.add(panel, BorderLayout.CENTER); this.add(hslider, BorderLayout.SOUTH); @@ -127,26 +134,62 @@ public class ArrangementDialog extends JPanel { private void addListener() { this.vslider.addChangeListener(e -> { JSlider slider = (JSlider) e.getSource(); - double delta = Math.abs(slider.getValue() - 50) * 0.1; - if (slider.getValue() < 50) { - domain.setRange(domainMin - delta, domainMax - delta); + double delta = Math.abs(slider.getValue() - 5000) * 0.1; + if (slider.getValue() < 5000) { + domain.setRange(domain.getLowerBound() - delta, domain.getUpperBound() - delta); } else { - domain.setRange(domainMin + delta, domainMax + delta); + domain.setRange(domain.getLowerBound() + delta, domain.getUpperBound() + delta); } }); this.hslider.addChangeListener(e -> { JSlider slider = (JSlider) e.getSource(); - double delta = Math.abs(slider.getValue() - 500); + double delta = Math.abs(slider.getValue() - 5000); - if (slider.getValue() < 500) { - range.setRange(rangeMin - delta, rangeMax - delta); + if (slider.getValue() < 5000) { + range.setRange(range.getLowerBound() - delta, range.getUpperBound() - delta); } else { - range.setRange(rangeMin + delta, rangeMax + delta); + range.setRange(range.getLowerBound() + delta, range.getUpperBound() + delta); } }); - } + protected void addZooming(ChartPanel chartPanel) { -} + chartPanel.addMouseWheelListener(new MouseWheelListener() { + + public void mouseWheelMoved(MouseWheelEvent e) { + Double x = Double.valueOf(e.getY()); + Double y = Double.valueOf(e.getY()); + if (e.getScrollType() != MouseWheelEvent.WHEEL_UNIT_SCROLL) + return; + if (e.getWheelRotation() < 0) + increaseZoom((ChartPanel) e.getComponent(), true, x, y); + else + decreaseZoom((ChartPanel) e.getComponent(), true, x, y); + } + + public synchronized void increaseZoom(JComponent chart, boolean saveAction, Double x, Double y) { + ChartPanel ch = (ChartPanel) chart; + zoomChartAxis(ch, true, x, y); + } + + public synchronized void decreaseZoom(JComponent chart, boolean saveAction, Double x, Double y) { + ChartPanel ch = (ChartPanel) chart; + zoomChartAxis(ch, false, x, y); + } + + private void zoomChartAxis(ChartPanel chartP, boolean increase, Double x, Double y) { + int width = chartP.getMaximumDrawWidth() - chartP.getMinimumDrawWidth(); + int height = chartP.getMaximumDrawHeight() - chartP.getMinimumDrawWidth(); + if (increase) { + chartP.zoomInBoth(width / 2, height / 2); + } else { + chartP.zoomOutBoth(width / 2, height / 2); + } + + } + }); + } + + } \ No newline at end of file diff --git a/src/main/java/View/MainFrame.java b/src/main/java/View/MainFrame.java index 0d04131..9b6e6c7 100644 --- a/src/main/java/View/MainFrame.java +++ b/src/main/java/View/MainFrame.java @@ -97,7 +97,11 @@ public class MainFrame extends JFrame { if (arrangement == null) { arrangement = new ArrangementDialog(); arrangement.setPrameters(getPresenter().calcArrangementLines(), - getPresenter().getModel().getNodes()); + getPresenter().getModel().getNodes(), + getPresenter().getModel().getxMinimum(), + getPresenter().getModel().getxMaximum(), + getPresenter().getModel().getyMinimum(), + getPresenter().getModel().getyMaximum()); arrangement.createArrangement(); SwingUtilities.invokeLater(() -> { arrangementDialog.add(arrangement, BorderLayout.CENTER); @@ -246,15 +250,19 @@ public class MainFrame extends JFrame { }); lmsPanel.getStartButton().addActionListener((ActionEvent e) -> { - Thread t = new Thread( - () -> this.getPresenter().calculateLMS(lmsPanel.getInput())); - t.start(); + if (lmsPanel.getInput() != null){ + Thread t = new Thread( + () -> this.getPresenter().calculateLMS(lmsPanel.getInput())); + t.start(); + } }); rmPanel.getStartButton().addActionListener((ActionEvent e) -> { - Thread t = new Thread( - () -> this.getPresenter().calculateRM(rmPanel.getInput())); - t.start(); + if (rmPanel.getInput() != null){ + Thread t = new Thread( + () -> this.getPresenter().calculateRM(rmPanel.getInput())); + t.start(); + } }); importButton.addActionListener((ActionEvent e) -> { diff --git a/src/main/java/View/Panels/LMSPanel.java b/src/main/java/View/Panels/LMSPanel.java index aec5218..055f74d 100644 --- a/src/main/java/View/Panels/LMSPanel.java +++ b/src/main/java/View/Panels/LMSPanel.java @@ -1,6 +1,7 @@ package View.Panels; import View.PlotDialog; +import com.sun.istack.internal.Nullable; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; @@ -13,6 +14,7 @@ import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JLabel; +import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.border.TitledBorder; @@ -57,8 +59,6 @@ public class LMSPanel extends JPanel { this.startButton = new JButton("Start"); this.startButton.setFont(new Font("Verdana",Font.PLAIN, 16)); - this.startButton.setContentAreaFilled(false); - this.startButton.setFocusPainted(false); addButton(2, startButton); this.northPanel.add(continer, BorderLayout.CENTER); @@ -107,11 +107,19 @@ public class LMSPanel extends JPanel { return startButton; } + @Nullable public String[] getInput() { String[] input = new String[3]; input[0] = this.input[0].getText(); input[1] = this.input[1].getText(); - return input; + + if (isNumeric(input[0]) && isNumeric(input[1])){ + return input; + } else { + JOptionPane.showMessageDialog(null, "Bitte geben Sie numerische Werte als Parameter an.","Fehler bei der Eingabe", JOptionPane.ERROR_MESSAGE); + return null; + } + } public void setInput(JTextField[] input) { @@ -129,4 +137,14 @@ public class LMSPanel extends JPanel { this.repaint(); this.revalidate(); } + + public boolean isNumeric(String str) { + try{ + double d = Double.parseDouble(str); + } + catch(NumberFormatException nfe){ + return false; + } + return true; + } } diff --git a/src/main/java/View/Panels/RMPanel.java b/src/main/java/View/Panels/RMPanel.java index 1459405..d06350b 100644 --- a/src/main/java/View/Panels/RMPanel.java +++ b/src/main/java/View/Panels/RMPanel.java @@ -1,7 +1,9 @@ package View.Panels; import View.PlotDialog; +import com.sun.istack.internal.Nullable; import java.awt.BorderLayout; +import java.awt.Color; import java.awt.FlowLayout; import java.awt.Font; import java.awt.GridBagConstraints; @@ -9,8 +11,10 @@ import java.awt.GridBagLayout; import java.awt.Insets; import javax.swing.JButton; import javax.swing.JLabel; +import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextField; +import javax.swing.border.LineBorder; import javax.swing.border.TitledBorder; /** @@ -55,8 +59,6 @@ public class RMPanel extends JPanel { buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); this.startButton = new JButton("Start"); this.startButton.setFont(new Font("Verdana",Font.PLAIN, 16)); - this.startButton.setContentAreaFilled(false); - this.startButton.setFocusPainted(false); gbc.insets = new Insets(30, 0, 10, 0); gbc.gridx = 0; gbc.gridy = 2; @@ -97,10 +99,15 @@ public class RMPanel extends JPanel { return startButton; } + @Nullable public String getInput() { String input = ""; input = this.input.getText(); - return input; + if (isNumeric(input)) + return input; + else + JOptionPane.showMessageDialog(null, "Bitte geben Sie numerische Werte als Parameter an.","Fehler bei der Eingabe", JOptionPane.ERROR_MESSAGE); + return null; } public void setInput(JTextField input) { @@ -118,4 +125,14 @@ public class RMPanel extends JPanel { this.repaint(); this.revalidate(); } + + public boolean isNumeric(String str) { + try{ + double d = Double.parseDouble(str); + } + catch(NumberFormatException nfe){ + return false; + } + return true; + } }