diff --git a/src/main/java/App.java b/src/main/java/App.java index fdc8e3f..5017f06 100644 --- a/src/main/java/App.java +++ b/src/main/java/App.java @@ -1,6 +1,6 @@ -import Model.LineModel; -import Presenter.Presenter; -import View.MainFrame; +import model.LineModel; +import presenter.Presenter; +import view.MainFrame; import javax.swing.*; import java.awt.*; @@ -14,46 +14,48 @@ import java.awt.*; */ public class App { - private static void setUIFont(javax.swing.plaf.FontUIResource f) - { - java.util.Enumeration keys = UIManager.getDefaults().keys(); - while (keys.hasMoreElements()) - { - Object key = keys.nextElement(); - Object value = UIManager.get(key); - if (value instanceof javax.swing.plaf.FontUIResource) - { - UIManager.put(key, f); - } + private static void setUIFont(javax.swing.plaf.FontUIResource f) { + java.util.Enumeration keys = UIManager.getDefaults().keys(); + while (keys.hasMoreElements()) { + Object key = keys.nextElement(); + Object value = UIManager.get(key); + if (value instanceof javax.swing.plaf.FontUIResource) { + UIManager.put(key, f); + } + } } - } - private static void setLookAndFeel(JFrame view){ - try { - UIManager.setLookAndFeel("com.jtattoo.plaf.aluminium.AluminiumLookAndFeel"); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (UnsupportedLookAndFeelException e) { - e.printStackTrace(); + private static void setLookAndFeel(JFrame view) { + String[] laf = {"com.jtattoo.plaf.aluminium.AluminiumLookAndFeel", + "com.jtattoo.plaf.acryl.AcrylLookAndFeel", + "com.jtattoo.plaf.aero.AeroLookAndFeel", + "com.jtattoo.plaf.fast.FastLookAndFeel", + "com.jtattoo.plaf.graphite.GraphiteLookAndFeel"}; + try { + UIManager.setLookAndFeel(laf[4]); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (UnsupportedLookAndFeelException e) { + e.printStackTrace(); + } + SwingUtilities.updateComponentTreeUI(view); } - SwingUtilities.updateComponentTreeUI(view); - } - public static void main(String[] args) { + public static void main(String[] args) { - SwingUtilities.invokeLater(() -> { - JFrame.setDefaultLookAndFeelDecorated(true); - MainFrame view = new MainFrame(); - setLookAndFeel(view); - setUIFont (new javax.swing.plaf.FontUIResource(new Font("Verdana",Font.PLAIN, 12))); + SwingUtilities.invokeLater(() -> { + JFrame.setDefaultLookAndFeelDecorated(true); + MainFrame view = new MainFrame(); + setLookAndFeel(view); + setUIFont(new javax.swing.plaf.FontUIResource(new Font("Verdana", Font.PLAIN, 12))); + view.setPresenter(new Presenter(new LineModel(), view)); + view.setActionListeners(); + }); - view.setPresenter(new Presenter(new LineModel(), view)); - }); - - } + } } diff --git a/src/main/java/Model/DCEL/DoublyConnectedEdgeList.java b/src/main/java/Model/DCEL/DoublyConnectedEdgeList.java deleted file mode 100644 index e9a9573..0000000 --- a/src/main/java/Model/DCEL/DoublyConnectedEdgeList.java +++ /dev/null @@ -1,153 +0,0 @@ -package Model.DCEL; - - -import Model.Point; -import java.util.LinkedList; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 30.05.2017. - */ -public class DoublyConnectedEdgeList { - - private LinkedList nodes; - private LinkedList edges; - private LinkedList faces; - - public DoublyConnectedEdgeList() { - this.nodes = new LinkedList<>(); - this.edges = new LinkedList<>(); - this.faces = new LinkedList<>(); - } - - public Node createNode(Point point, String id) { - - Node node = new Node(); - node.setPoint(point); - node.setID(id); - - return node; - } - - public Edge createEdge(Node source, Node destination, String id) { - - Edge edge = new Edge(); - Edge twin = new Edge(); - - edge.setOrigin(source); - edge.setID(id); - edge.setTwin(twin); - twin.setOrigin(destination); - twin.setID("#" + id); - twin.setTwin(edge); - - source.setIncidentEdge(edge); - destination.setIncidentEdge(twin); - - return edge; - } - - public Face createFace(Edge outerComponent, Edge innerComponent, String id) { - - Face face = new Face(outerComponent, null); - face.setID(id); - Edge tempEdge; - - if (outerComponent != null) { - tempEdge = outerComponent; - do { - tempEdge.setIncidentFace(face); - tempEdge = tempEdge.getNext(); - } while (!tempEdge.equals(outerComponent)); - } - - if (innerComponent != null) { - LinkedList componentlist; - componentlist = face.getInnerComponents(); - componentlist.add(innerComponent); - tempEdge = innerComponent; - do { - tempEdge.setIncidentFace(face); - tempEdge = tempEdge.getNext(); - } while (!tempEdge.equals(innerComponent)); - } - - return face; - } - - public void createConnection(Edge edge, Edge succ) { - edge.setNext(succ); - succ.setPrev(edge); - - edge.getTwin().setPrev(succ.getTwin()); - succ.getTwin().setNext(edge.getTwin()); - } - - public LinkedList getEdgesOfInnerComponents(Face face) { - - LinkedList list = new LinkedList(); - LinkedList innerComponents = face.getInnerComponents(); - Edge it; - for (Edge e : innerComponents) { - it = e; - do { - list.add(it); - //System.out.println("Current Edge: "+it.getID()+"\tNext Edge: "+it.getNext().getID()); - it = it.getNext(); - } while (it != e); - } - - return list; - } - - public LinkedList getEdgesOfOuterComponents(Face face) { - - LinkedList list = new LinkedList(); - Edge it = face.getOuterComponent(); - do { - list.add(it); - //System.out.println("Current Edge: "+it.getID()+"\tNext Edge: "+it.getNext().getID()); - it = it.getNext(); - } while (it != face.getOuterComponent()); - - return list; - } - - - public LinkedList getConnectedEdges(Node node) { - Edge edge = node.getIncidentEdge(); - LinkedList list = new LinkedList(); - do { - list.add(edge); - edge = edge.getNext(); - } while (node != edge.getOrigin()); - return list; - } - - public LinkedList getNodes() { - return nodes; - } - - public void setNodes(LinkedList nodes) { - this.nodes = nodes; - } - - public LinkedList getEdges() { - return edges; - } - - public void setEdges(LinkedList edges) { - this.edges = edges; - } - - public LinkedList getFaces() { - return faces; - } - - public void setFaces(LinkedList faces) { - this.faces = faces; - } -} diff --git a/src/main/java/Model/DCEL/Edge.java b/src/main/java/Model/DCEL/Edge.java deleted file mode 100644 index 6496326..0000000 --- a/src/main/java/Model/DCEL/Edge.java +++ /dev/null @@ -1,117 +0,0 @@ -package Model.DCEL; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 30.05.2017. - */ -public class Edge { - - private Node origin; - private Edge twin; - private Face incidentFace; - private Edge next; - private Edge prev; - private String id; - - public Edge() { - new Edge(null, null, null, null, null); - } - - public Edge(Node origin, Edge twin, Edge next, Edge prev, Face incidentFace) { - this.origin = origin; - this.twin = twin; - this.next = next; - this.prev = prev; - this.incidentFace = incidentFace; - } - - public Node getOrigin() { - return origin; - } - - public void setOrigin(Node origin) { - this.origin = origin; - } - - public Edge getTwin() { - return twin; - } - - public void setTwin(Edge twin) { - this.twin = twin; - } - - public Face getIncidentFace() { - return incidentFace; - } - - public void setIncidentFace(Face incidentFace) { - this.incidentFace = incidentFace; - } - - public Edge getNext() { - return next; - } - - public void setNext(Edge next) { - this.next = next; - } - - public Edge getPrev() { - return prev; - } - - public void setPrev(Edge prev) { - this.prev = prev; - } - - public boolean hasNext() { - if (getNext() == null) { - return false; - } else { - return true; - } - - } - - public Edge insertNode(Node node) { - - Edge edge = new Edge(); - Edge twin = new Edge(); - - edge.setOrigin(node); - edge.setNext(this.getNext()); - edge.setPrev(this); - edge.setTwin(twin); - edge.setIncidentFace(this.getIncidentFace()); - - twin.setOrigin(this.getTwin().getOrigin()); - twin.setPrev(this.getTwin().getPrev()); - twin.setNext(this.getTwin()); - twin.setTwin(edge); - twin.setIncidentFace(this.getTwin().getIncidentFace()); - - Node twinOrigin = this.getTwin().getOrigin(); - twinOrigin.setIncidentEdge(twin); - node.setIncidentEdge(edge); - - this.getTwin().setOrigin(node); - this.getTwin().getPrev().setNext(twin); - this.getNext().setPrev(edge); - this.setNext(edge); - this.getTwin().setPrev(twin); - - return edge; - } - - public String getID() { - return this.id; - } - - public void setID(String id) { - this.id = id; - } -} diff --git a/src/main/java/Model/DCEL/Face.java b/src/main/java/Model/DCEL/Face.java deleted file mode 100644 index 7772978..0000000 --- a/src/main/java/Model/DCEL/Face.java +++ /dev/null @@ -1,125 +0,0 @@ -package Model.DCEL; - -import java.util.LinkedList; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 30.05.2017. - */ -public class Face { - - private LinkedList innerComponents; - private Edge outerComponent; - private String id; - - public Face() { - this.outerComponent = null; - this.innerComponents = new LinkedList<>(); - } - - public Face(Edge outerComponent, LinkedList innerComponents) { - this.outerComponent = outerComponent; - if (innerComponents != null) { - this.innerComponents = innerComponents; - } else { - this.innerComponents = new LinkedList<>(); - - } - - } - - public LinkedList getInnerComponents() { - return innerComponents; - } - - public void setInnerComponents(LinkedList innerComponents) { - this.innerComponents = innerComponents; - } - - public Edge getOuterComponent() { - return outerComponent; - } - - public void setOuterComponent(Edge outerComponent) { - this.outerComponent = outerComponent; - } - - public Face insertEdge(Edge edgeWithSameDestination, Edge edgeToMySource) { - - if (edgeWithSameDestination.getIncidentFace().equals(this) || edgeToMySource.getIncidentFace() - .equals(this)) { - LinkedList components = new LinkedList(); - for (Edge e : innerComponents) { - components.add(e); - } - Face face = new Face(getOuterComponent(), components); - Edge edge = new Edge(); - Edge twin = new Edge(); - - edge.setOrigin(edgeWithSameDestination.getOrigin()); - edge.setTwin(twin); - edge.setNext(edgeToMySource); - edge.setPrev(edgeWithSameDestination.getPrev()); - - twin.setOrigin(edgeToMySource.getOrigin()); - twin.setTwin(edge); - twin.setNext(edgeWithSameDestination); - twin.setPrev(edgeToMySource.getPrev()); - - Edge tempEdge = edge.getNext(); - Edge tempTwin = twin.getNext(); - //kreis umlaufen um festzustellen welche fläche kleiner ist - while ((tempEdge.equals(edge) == false) && (tempTwin.equals(twin) == false)) { - tempEdge = tempEdge.getNext(); - tempTwin = tempTwin.getNext(); - } - - if (tempEdge.equals(edge)) { - setOuterComponent(twin); - twin.setIncidentFace(this); - face.setOuterComponent(edge); - } else { - setOuterComponent(edge); - edge.setIncidentFace(this); - face.setOuterComponent(twin); - } - - LinkedList bla = new LinkedList(); - Edge iterEdge = face.getOuterComponent(); - bla.add(face.getOuterComponent()); - - while (iterEdge.hasNext()) { - bla.add(iterEdge.getNext()); - iterEdge = iterEdge.getNext(); - } - - for (Edge e : face.getInnerComponents()) { - iterEdge = e; - while (iterEdge.hasNext()) { - bla.add(iterEdge.getNext()); - iterEdge = iterEdge.getNext(); - } - } - - for (Edge e : bla) { - e.setIncidentFace(face); - } - return face; - } else { - throw new IllegalArgumentException( - "Die angegebenen Kanten haben keinen zusammenhang mit der Fläche!"); - } - - } - - public String getID() { - return this.id; - } - - public void setID(String id) { - this.id = id; - } -} diff --git a/src/main/java/Model/DCEL/Node.java b/src/main/java/Model/DCEL/Node.java deleted file mode 100644 index 028cf74..0000000 --- a/src/main/java/Model/DCEL/Node.java +++ /dev/null @@ -1,50 +0,0 @@ -package Model.DCEL; - -import Model.Point; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 30.05.2017. - */ -public class Node { - - private Point point; - private Edge incidentEdge; - private String id; - - public Node() { - new Node(null, null); - } - - public Node(Point point, Edge incidentEdge) { - this.point = point; - this.incidentEdge = incidentEdge; - } - - public Point getPoint() { - return point; - } - - public void setPoint(Point point) { - this.point = point; - } - - public Edge getIncidentEdge() { - return incidentEdge; - } - - public void setIncidentEdge(Edge incidentEdge) { - this.incidentEdge = incidentEdge; - } - - public String getID() { - return this.id; - } - - public void setID(String id) { - this.id = id; - } -} diff --git a/src/main/java/Model/Interval.java b/src/main/java/Model/Interval.java deleted file mode 100644 index 89263c1..0000000 --- a/src/main/java/Model/Interval.java +++ /dev/null @@ -1,51 +0,0 @@ -package Model; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 16.06.2017. - */ -public class Interval { - - private double upper; - private double lower; - private Boolean activity; - - public Interval(double lower, double upper) { - this.upper = upper; - this.lower = lower; - this.activity = true; - } - - public Boolean getActivity() { - return activity; - } - - public void setActivity(Boolean isActive) { - this.activity = isActive; - } - - public double getUpper() { - return upper; - } - - public void setUpper(double upper) { - this.upper = upper; - } - - public double getLower() { - return lower; - } - - public void setLower(double lower) { - this.lower = lower; - } - - public Double getDistance() { - - return Math.abs(this.upper - this.lower); - } - -} \ No newline at end of file diff --git a/src/main/java/Model/Line.java b/src/main/java/Model/Line.java deleted file mode 100644 index aae2401..0000000 --- a/src/main/java/Model/Line.java +++ /dev/null @@ -1,107 +0,0 @@ -package Model; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 12.06.2017. - */ -public class Line { - - private final Double MAX = 9999d; - private final Double MIN = -9999d; - - - private Double m; - private Double b; - - private Double x1; - private Double x2; - private Double y1; - private Double y2; - - private String id; - - public Line(double m, double b, String id) { - this.m = m; - this.b = b; - - this.x1 = MIN; - this.y1 = (MIN * m) + b; - this.x2 = MAX * 0.5; - this.y2 = ((MAX * 0.5) * m) + b; - this.id = id; - } - - - public Line(double m, double b) { - this.m = m; - this.b = b; - - this.x1 = MIN; - this.y1 = (MIN * m) + b; - this.x2 = MAX * 0.5; - this.y2 = ((MAX * 0.5) * m) + b; - } - - public Line(double x1, double x2, double y1, double y2) { - this.x1 = x1; - this.x2 = x2; - this.y1 = y1; - this.y2 = y2; - - this.m = (y2 - y1) / (x2 - x1); - this.b = y2 - (x2 * m); - - } - - public Double getM() { - return m; - } - - public void setM(double m) { - this.m = m; - } - - public Double getB() { - return b; - } - - public void setB(double b) { - this.b = b; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public Double getX1() { - return x1; - } - - public Double getX2() { - return x2; - } - - public Double getY1() { - return y1; - } - - public Double getY2() { - return y2; - } - - public void setEndPoints(double x1, double y1, double x2, double y2) { - this.x1 = x1; - this.x2 = x2; - this.y1 = y1; - this.y2 = y2; - } - - -} diff --git a/src/main/java/Model/LineModel.java b/src/main/java/Model/LineModel.java deleted file mode 100644 index 4a8fcde..0000000 --- a/src/main/java/Model/LineModel.java +++ /dev/null @@ -1,98 +0,0 @@ -package Model; - -import java.util.Collections; -import java.util.LinkedList; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 28.05.2017. - */ -public class LineModel { - - private LinkedList nodes; - private LinkedList lines; - private Double xMinimum; - private Double xMaximum; - private Double yMinimum; - private Double yMaximum; - - public LineModel() { - nodes = new LinkedList<>(); - lines = new LinkedList<>(); - } - - public void setXbounds(){ - LinkedList xlist = new LinkedList<>(); - for (Point p : nodes){ - xlist.add(p.getX()); - } - - xMaximum = Collections.max(xlist); - xMinimum = Collections.min(xlist); - } - - public void setYbounds(){ - LinkedList ylist = new LinkedList<>(); - for (Point p : nodes){ - ylist.add(p.getY()); - } - - yMaximum = Collections.max(ylist); - yMinimum = Collections.min(ylist); - } - - public void addNode(Point node) { - this.nodes.add(node); - } - - public void addLine(Line line) { - this.lines.add(line); - } - - public LinkedList getNodes() { - return nodes; - } - - public LinkedList getLines() { - return lines; - } - - public void setLines(LinkedList lines) { - 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/Model/Pair.java b/src/main/java/Model/Pair.java deleted file mode 100644 index 8a2f0f5..0000000 --- a/src/main/java/Model/Pair.java +++ /dev/null @@ -1,35 +0,0 @@ -package Model; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 19.06.2017. - */ -public class Pair { - - private Integer p1; - private Integer p2; - - public Pair(Integer p1, Integer p2) { - this.p1 = p1; - this.p2 = p2; - } - - public Integer getP1() { - return p1; - } - - public void setP1(Integer p1) { - this.p1 = p1; - } - - public Integer getP2() { - return p2; - } - - public void setP2(Integer p2) { - this.p2 = p2; - } -} diff --git a/src/main/java/Model/Point.java b/src/main/java/Model/Point.java deleted file mode 100644 index 0793977..0000000 --- a/src/main/java/Model/Point.java +++ /dev/null @@ -1,65 +0,0 @@ -package Model; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 28.05.2017. - */ -public class Point implements Comparable { - - private Double x; - private Double y; - private String id; - - public Point(Double x, Double y) { - this.x = x; - this.y = y; - } - - public Point(Double x, Double y, String id) { - this.x = x; - this.y = y; - this.id = id; - } - - public Double getX() { - return x; - } - - public void setX(Double x) { - this.x = x; - } - - public Double getY() { - return y; - } - - public void setY(Double y) { - this.y = y; - } - - @Override - public int compareTo(Point o) { - if (this.getX() == o.getX()) { - if (this.getY() <= o.getY()) { - return -1; - } else { - return 1; - } - } else if (this.getX() < o.getX()) { - return -1; - } else { - return 1; - } - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } -} diff --git a/src/main/java/Presenter/Algorithms/BinomialCoeffizient.java b/src/main/java/Presenter/Algorithms/BinomialCoeffizient.java deleted file mode 100644 index 0da693f..0000000 --- a/src/main/java/Presenter/Algorithms/BinomialCoeffizient.java +++ /dev/null @@ -1,30 +0,0 @@ -package Presenter.Algorithms; - -import Presenter.Presenter; - -import java.util.Collections; -import java.util.LinkedList; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 26.06.2017. - */ -public class BinomialCoeffizient { - - public static Double run(int n, int k) { - int res = 1; - - if ( k > n - k ) - k = n - k; - - for (int i = 0; i < k; ++i){ - res *= (n - i); - res /= (i + 1); - } - - return Double.valueOf(res); - } -} diff --git a/src/main/java/Presenter/Algorithms/IntersectionCounter.java b/src/main/java/Presenter/Algorithms/IntersectionCounter.java deleted file mode 100644 index 37e75f1..0000000 --- a/src/main/java/Presenter/Algorithms/IntersectionCounter.java +++ /dev/null @@ -1,272 +0,0 @@ -package Presenter.Algorithms; - -import Model.*; -import Presenter.Algorithms.Comparators.YOrderLineComparatorBegin; -import Presenter.Algorithms.Comparators.YOrderLineComparatorEnd; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -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: 18.06.2017. - */ -public class IntersectionCounter { - - private HashMap dictionaryTO; - private HashMap dictionaryBACK; - private ArrayList substituted; - private ArrayList inversions; - private List set; - - //indexieren der Punkte damit die schnittpunkte berechnet werden können - private HashMap secondaryDictionaryTO; - private HashMap secondaryDictionaryBACK; - private ArrayList umin; - - /** - * Berechnet die Inversionen zwischen zwei Listen mit Integer Werten. Diese Methode dient als - * Wrapper Methode. Die Logik steht in der countInversions Funktion. - * - * @param a Liste - * @param b Liste - * @return Anzahl an Inversionen - */ - public int run(List a, List b) { - - dictionaryTO = new HashMap<>(); - dictionaryBACK = new HashMap<>(); - substituted = new ArrayList<>(); - inversions = new ArrayList<>(); - - ArrayList temp = new ArrayList<>(); - - temp.addAll(a); - - for (int i = 0; i < a.size(); i++) { - dictionaryTO.put(a.get(i), i + 1); - dictionaryBACK.put(i + 1, a.get(i)); - } - - for (int j = 0; j < b.size(); j++) { - substituted.add(dictionaryTO.get(b.get(j))); - } - - int ret = countInversions(substituted, 0, substituted.size() - 1, temp); - - return ret; - } - - /** - * Wrapper Methode um herauszufinden wieviele Inversionen zwischen den Schnittpunkten der Werte - * in der Liste und den Endpunkten des Intervalls entstehen. - * - * @param set Liste mit Werten (m,b) um Schnittpunkte zu berechnen - * @param interval Interval - * @return Anzahl an Inversionen - */ - public int run(List set, Interval interval) { - ArrayList listA = new ArrayList<>(); - ArrayList listB = new ArrayList<>(); - - prepareData(set, interval, listA, listB); - return run(listA, listB); - } - - /** - * Methode die, die Daten für die Funktion run vorbereitet. Es werden die Schnittpunkte - * bzgl. der unteren und oberen Grenze des Intervals und den Werten der Liste (m,b) berechnet. Diese - * Werte haben die selbe x Koordinate aber verschiedene y Koordinaten. - * - * @param set Liste mit Werten m,b - * @param interval Interval - * @param listA Schnittpunkte bzgl. unteren Grenze - * @param listB Schnittpunkte bzgl. oberen Grenze - */ - private void prepareData(List set, Interval interval, ArrayList listA, - ArrayList listB) { - secondaryDictionaryTO = new HashMap<>(); - secondaryDictionaryBACK = new HashMap<>(); - this.set = set; - umin = new ArrayList<>(); - Line tmpLine; - - for (Line p : set) { - //vertauscht das Point standardmäßig die x lexikografische Ordnung betrachtet - tmpLine = new Line(p.getM(), p.getM(), interval.getLower() * p.getM() + p.getB(), - interval.getUpper() * p.getM() + p.getB()); - //wird benötigt um späer die Schnittpunkte ermitteln zu können - tmpLine.setB(p.getB()); - tmpLine.setM(p.getM()); - umin.add(tmpLine); - } - - for (int i = 0; i < umin.size(); i++) { - secondaryDictionaryTO.put(umin.get(i), i); - secondaryDictionaryBACK.put(i, this.set.get(i)); - } - - Collections.sort(umin, new YOrderLineComparatorBegin()); - for (Line q : umin) { - listA.add(secondaryDictionaryTO.get(q)); - } - - Collections.sort(umin, new YOrderLineComparatorEnd()); - for (Line q : umin) { - listB.add(secondaryDictionaryTO.get(q)); - } - - } - - - /** - * Angepasster Merge-Sort Algorithmus. - * Die Funktion bekommt neben den standard Parametern zusätzlich eine Liste mit Elementen - * die als Groundtruth dienen. - * - * @param a Eingabefeld mit den Elementen die überprüft werden sollen. - * @param start Startpunkt des Eingabefeldes. - * @param end Endpunkt des Eingabefeldes. - * @param aux Temporäres Array das beim Mergen eine Kopie des original Arrays ist. - * @return Anzahl der inversionen zwischen a und aux. - */ - public int countInversions(List a, int start, int end, List aux) { - if (start >= end) { - return 0; - } - int invCount = 0; - int mid = start + (end - start) / 2; - int invCountLeft = countInversions(a, start, mid, aux); // divide and conquer - int invCountRight = countInversions(a, mid + 1, end, aux); // divide and conquer - invCount += (invCountLeft + invCountRight); - for (int i = start; i <= end; i++) { - aux.set(i, a.get(i)); - } - int left = start; - int right = mid + 1; - int index = start; - //hier beginnt das merging - //iteriere über die Teillisten - //Two-way Merge - Knuth Vol 3 The Art of Computer Programming - - while (left <= mid && right <= end) { - //wenn die linke Teilliste das kleinere Element besitzt kopiere - //das Element in das neue Array - if (aux.get(left) < aux.get(right)) { - a.set(index++, aux.get(left++)); - } else { - //merke die inversionspaare - for (int i = left; i <= mid; i++) { - // System.out.println(aux.get(i)+" -- "+ aux.get(right)); - inversions.add(new Pair(aux.get(i), aux.get(right))); - } - a.set(index++, aux.get(right++)); - invCount += mid - left + 1; // number of inversions for aux[right] - } - } - while (left <= mid) { - a.set(index++, aux.get(left++)); - } - // no need to copy over remaining aux[right++] because they are already inside a - return invCount; - } - - /** - * Diese Methode liefert nur nach dem Ausführen der run Funktion Sinnvolle Werte. - * - * @return Map mit Schnittpunkt Paaren. - */ - public HashMap> getIntersectionLinePairs() { - ArrayList result = new ArrayList<>(); - HashMap> ret = new HashMap<>(); - - for (int i = 0; i < inversions.size(); i++) { - result.add(new Pair(dictionaryBACK.get(inversions.get(i).getP1()), - dictionaryBACK.get(inversions.get(i).getP2()))); - } - ArrayList linePairs; - - for (Pair p : result) { - Line l1 = secondaryDictionaryBACK.get(p.getP1()); - Line l2 = secondaryDictionaryBACK.get(p.getP2()); - if (ret.get(l2) == null){ - linePairs = new ArrayList<>(); - } else { - linePairs = ret.get(l2); - } - linePairs.add(l1); - ret.put(l2, linePairs); - - //Symetrie - if (ret.get(l1) == null){ - linePairs = new ArrayList<>(); - } else { - linePairs = ret.get(l1); - } - linePairs.add(l2); - ret.put(l1, linePairs); - } - /*System.out.println("----------------------------------------------------------"); - for (Line outerLine : ret.keySet()){ - System.out.println("Linie: "+outerLine); - for (Line innerLine : ret.get(outerLine)){ - System.out.println("\t\t -> "+innerLine); - } - } - System.out.println("----------------------------------------------------------");*/ - - return ret; - } - - /** - * Diese Methode liefert nur nach dem Ausführen der run Funktion Sinnvolle Werte. - */ - public void calculateIntersectionAbscissas(LineModel model){ - ArrayList result = new ArrayList<>(); - - for (int i = 0; i < inversions.size(); i++) { - result.add(new Pair(dictionaryBACK.get(inversions.get(i).getP1()), - dictionaryBACK.get(inversions.get(i).getP2()))); - } - - for (Pair p : result) { - Line line = secondaryDictionaryBACK.get(p.getP1()); - Line sampledLine = secondaryDictionaryBACK.get(p.getP2()); - if (!line.equals(sampledLine)){ - double intersection = (line.getB() - sampledLine.getB()) / (sampledLine.getM() - line.getM()); - double yintercept = sampledLine.getM() * intersection + sampledLine.getB(); - model.addNode(new Point(intersection, yintercept)); - } - } - - } - - /** - * Berechnet die Schnittpunkte zwischen einer gegebenen Gerade und einer Menge an Geraden. - * - * @param set Menge an Geraden - * @param sampledLine eine spezielle Gerade - * @return Liste mit x Koordinaten der Schnittpunkte - */ - public ArrayList calculateIntersectionAbscissas(ArrayList set, Line sampledLine){ - LinkedList lines = new LinkedList<>(set); - ArrayList intersections = new ArrayList<>(); - double intersection; - - for (Line line : lines) { - if (line != sampledLine) { - intersection = (line.getB() - sampledLine.getB()) / (sampledLine.getM() - line.getM()); - intersections.add(intersection); - } - } - - return intersections; - } - - -} diff --git a/src/main/java/Presenter/Algorithms/LeastMedianOfSquaresEstimator.java b/src/main/java/Presenter/Algorithms/LeastMedianOfSquaresEstimator.java deleted file mode 100644 index 9b89a78..0000000 --- a/src/main/java/Presenter/Algorithms/LeastMedianOfSquaresEstimator.java +++ /dev/null @@ -1,484 +0,0 @@ -package Presenter.Algorithms; - -import Model.Interval; -import Model.Line; -import Model.Point; -import Presenter.*; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.LinkedList; -import java.util.Observable; -import java.util.PriorityQueue; -import java.util.Random; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 28.05.2017. - */ -public class LeastMedianOfSquaresEstimator extends Observable implements Algorithm { - - - private Presenter presenter; - - private LinkedList set = new LinkedList<>(); - private LinkedList intersections = new LinkedList<>(); - private IntersectionCounter invCounter = new IntersectionCounter(); - private int n; - private double quantileError; - private int kPlus; - private int kMinus; - private PriorityQueue intervals; - private Interval subSlabU1; - private Interval subSlabU2; - private Line sigmaMin; - private double heightsigmaMin; - private Double intersectionsPoint; - private Double constant = 0.5; - - private Double slope; - private Double yInterception; - - public LeastMedianOfSquaresEstimator(LinkedList set, LinkedList intersections, - Presenter presenter) { - this.set = set; - this.intersections = intersections; - - //(1.) Let n <- |S|; q+ <- q; q- <- q+ * (1 - quantileError);.... - n = set.size(); - double quantile = 0.5; - double qPlus = quantile; - quantileError = 0.1; - double qMinus = qPlus * (1 - quantileError); - kMinus = (int) Math.ceil(n * qMinus); - kPlus = (int) Math.ceil(n * qPlus); - this.presenter = presenter; - } - - public LeastMedianOfSquaresEstimator(LinkedList set, LinkedList intersections) { - this(set, intersections, null); - } - - /** - * - */ - public void run() { - - //(2.) Let U <- (-inf, inf) be the initial active intervals... - Comparator comparator = (o1, o2) -> { - if (o1.getDistance() < o2.getDistance()) { - return -1; - } - if (o1.getDistance() > o2.getDistance()) { - return 1; - } else { - return 0; - } - }; - intervals = new PriorityQueue<>(comparator); - intervals.add(new Interval(-100000, 100000)); - heightsigmaMin = Double.MAX_VALUE; - LinkedList tmpIntersections = intersections; - - //(3.) Apply the following steps as long as the exists active intervals - boolean active = true; - Interval interval; - while (!this.intervals.isEmpty()) { - interval = this.intervals.peek(); - if (interval.getActivity()) { - //(a.) Select any active Interval and calc. the inversions - int numberOfIntersections = countInversions(interval); - - //(b.) apply plane sweep - if ((constant * n) >= numberOfIntersections) { - sigmaMin = planeSweep(interval); - } else { - //(c.) otherwise.... - // get random intersections point... - Collections.shuffle(tmpIntersections, new Random()); - for (int i = 0; i < tmpIntersections.size(); i++) { - if (tmpIntersections.get(i).getX() > interval.getLower() - && tmpIntersections.get(i).getX() < interval.getUpper()) { - intersectionsPoint = tmpIntersections.get(i).getX(); - break; - } else { - intersectionsPoint = null; - } - } - - if (intersectionsPoint != null) { - splitActiveSlab(intersectionsPoint, interval); - //(d.) this may update sigma min - upperBound(intersectionsPoint); - //(e.) for i={1,2}, call lower bound(Ui) - lowerBound(subSlabU1); - lowerBound(subSlabU2); - - if (subSlabU1.getActivity()) { - this.intervals.add(subSlabU1); - } - if (subSlabU2.getActivity()) { - this.intervals.add(subSlabU2); - } - - } else { - this.intervals.poll(); - } - } - - - } else { - this.intervals.remove(interval); - } - } - } - - /** - * @param interval - * @return - */ - public int countInversions(Interval interval) { - - int numberOfInversions = 0; - // debug - //for (int i=0;i xQueue = new ArrayList<>(); - for (Point point : intersections) { - if (point.getX() >= interval.getLower() && point.getX() < interval.getUpper()) { - xQueue.add(point); - } - } - Collections.sort(xQueue); - - Line bracelet = sigmaMin; - double heightOfBracelet = heightsigmaMin; - - for (Point current : xQueue) { - Double[] currentBracelet = calcKMinusBracelet(current, kMinus); - - if (currentBracelet == null) { - continue; - } else if (currentBracelet[0] < heightOfBracelet) { - heightOfBracelet = currentBracelet[0]; - bracelet = new Line(current.getX(), current.getX(), currentBracelet[1], currentBracelet[2]); - } - } - - interval.setActivity(false); - return bracelet; - } - - /** - * Diese Methode spaltet den aktiven Interval an der x Koordinate point. Es werden zwei neue Slabs - * erzeugt. - * - * @param point x Koordinate an der, der Split geschieht. - */ - public void splitActiveSlab(double point, Interval active) { - subSlabU1 = new Interval(active.getLower() + 0.01, point); - subSlabU2 = new Interval(point, active.getUpper()); - - this.intervals.remove(active); - } - - /** - * - * @param point - */ - public void upperBound(double point) { - - double height = heightsigmaMin; - double tmpHeight; - ArrayList sortedLineSequence = getEjValues(point); - - int itnbr = ((n - kMinus) + 1); - for (int i = 0; i < itnbr; i++) { - tmpHeight = sortedLineSequence.get((i + kMinus) - 1) - sortedLineSequence.get(i); - if (tmpHeight < height) { - height = tmpHeight; - } - - if (height < heightsigmaMin) { - heightsigmaMin = height; - if (sigmaMin != null) { - sigmaMin.setEndPoints(point, sortedLineSequence.get(i) - , point, sortedLineSequence.get((i + kMinus) - 1)); - } else { - sigmaMin = new Line(point, point, sortedLineSequence.get(i), - sortedLineSequence.get((i + kMinus) - 1)); - } - } - } - - } - - /** - * @param pslab - * @return - */ - public void lowerBound(Interval pslab) { - - int[] alpha = new int[n]; - int[] beta = new int[n]; - int strictlyGreater = 0; - - //Teil I. - ArrayList umaxList; - ArrayList uminList; - - //y koordinaten der Schnittpunkte - ArrayList lines = new ArrayList<>(); - for (Line p : set) { - lines.add( - new Line(pslab.getLower(), pslab.getUpper(), ((pslab.getLower() * p.getM()) + p.getB()), - ((pslab.getUpper() * p.getM()) + p.getB()))); - } - - umaxList = getEjValues(pslab.getUpper()); - uminList = getEjValues(pslab.getLower()); - - for (int i = 0; i < n; i++) { - Line level = new Line(pslab.getLower(), pslab.getUpper(), uminList.get(i), umaxList.get(i)); - for (Line line : lines) { - if ((line.getY1() < level.getY1()) && (line.getY2() < level.getY2())) { - alpha[i]++; - } - - if ((line.getY1() > level.getY1()) && (line.getY2() > level.getY2())) { - strictlyGreater++; - } - } - beta[i] = n - (alpha[i] + strictlyGreater); - strictlyGreater = 0; - } - //TEST der Alpha und Beta werte, siehe JUnit Test - //for (int i=0;i= n) { - //System.out.println("i: "+i+", j:"+j+". ungültig"); - pslab.setActivity(false); - break; - } else { - h = Math.min(Math.abs(uminList.get(j) - uminList.get(i)), - Math.abs(umaxList.get(j) - umaxList.get(i))); - double error = 0.01; - if (((1 + error) * h) < heightsigmaMin) { - //System.out.println("h: "+ h +" ist kleiner als height(sigmaMin): "+heightsigmaMin); - pslab.setActivity(true); - return; - } - } - i = 0; - } - - } - - /** - * Berechnet die Schnittpunkte der Geraden und der vertikalen Gerade u. Im paper sind diese Werte - * als e_j Werte bekannt. - * - * @param u vertikale Gerade - * @return Liste der Schnittpunkte (da u bekannt werden nur die y Werte zurück gegeben) - */ - public ArrayList getEjValues(double u) { - - ArrayList ret = new ArrayList<>(); - - for (Line p : set) { - ret.add((p.getM() * u) + p.getB()); - } - - Collections.sort(ret); - - return ret; - } - - /** - * Die Funktion berechnet anhand einer vertikalen Gerade x = px das sogenannte kleinste kMinus - * Bracelet. Mit anderen Worten es wird eine vertikale Teilgerade berechnet die mindestens kMinus - * Geraden schneidet und dabei minimal ist. - * - * @param px Koordinate um die "vertikale Gerade" zu simulieren. - * @return Das Array enthält höhe des Bracelet, e_j und e_(j + kMinus - 1) - */ - public Double[] calcKMinusBracelet(Point px, int kMinusValue) { - - //y Koordinaten für das kMinus brecalet - LinkedList intersections = new LinkedList<>(); - for (Line line : set) { - intersections.add((px.getX() * line.getM()) + line.getB()); - } - if (intersections.size() >= kMinusValue) { - Collections.sort(intersections); - double height = Math.abs(intersections.get(0) - intersections.get(0 + kMinusValue - 1)); - Double[] ret = {height, intersections.get(0), intersections.get(0 + kMinusValue - 1)}; - return ret; - } else { - return null; - } - - } - - @Override - public void getResult() { - if (presenter != null) { - setChanged(); - double m = (getSigmaMin().getX2() + getSigmaMin().getX1()) * 0.5; - double b = (getSigmaMin().getY2() + getSigmaMin().getY1()) * -0.5; - - slope = m; - yInterception = b; - - String[] result = {"lms", m+"", b+""}; - notifyObservers(result); - } else { - double m = (getSigmaMin().getX2() + getSigmaMin().getX1()) * 0.5; - double b = (getSigmaMin().getY2() + getSigmaMin().getY1()) * -0.5; - - slope = m; - yInterception = b; - } - } - - /** - * Im Allgemeinen werden keine Getter und Setter Methoden benötigt aber sie sind nützlich bei den - * JUnit Testfällen. - */ - - public LinkedList getSet() { - return set; - } - - public void setSet(LinkedList set) { - this.set = set; - } - - public LinkedList getIntersections() { - return intersections; - } - - public void setIntersections(LinkedList intersections) { - this.intersections = intersections; - } - - public int getN() { - return n; - } - - public void setN(int n) { - this.n = n; - } - - public double getQuantileError() { - return quantileError; - } - - public void setQuantileError(double quantileError) { - this.quantileError = quantileError; - } - - public int getkPlus() { - return kPlus; - } - - public void setkPlus(int kPlus) { - this.kPlus = kPlus; - } - - public int getkMinus() { - return kMinus; - } - - public void setkMinus(int kMinus) { - this.kMinus = kMinus; - } - - public Interval getSubSlabU1() { - return subSlabU1; - } - - public void setSubSlabU1(Interval subSlabU1) { - this.subSlabU1 = subSlabU1; - } - - public Interval getSubSlabU2() { - return subSlabU2; - } - - public void setSubSlabU2(Interval subSlabU2) { - this.subSlabU2 = subSlabU2; - } - - public Line getSigmaMin() { - return sigmaMin; - } - - public void setSigmaMin(Line sigmaMin) { - this.sigmaMin = sigmaMin; - } - - public double getHeightsigmaMin() { - return heightsigmaMin; - } - - public void setHeightsigmaMin(double heightsigmaMin) { - this.heightsigmaMin = heightsigmaMin; - } - - public double getIntersectionsPoint() { - return intersectionsPoint; - } - - public void setIntersectionsPoint(double intersectionsPoint) { - this.intersectionsPoint = intersectionsPoint; - } - - public Double getConstant() { - return constant; - } - - public void setConstant(Double constant) { - this.constant = constant; - } - - public Double getSlope() { - return slope; - } - - public Double getyInterception() { - return yInterception; - } -} diff --git a/src/main/java/Presenter/Algorithms/RandomSampler.java b/src/main/java/Presenter/Algorithms/RandomSampler.java deleted file mode 100644 index 5127bbc..0000000 --- a/src/main/java/Presenter/Algorithms/RandomSampler.java +++ /dev/null @@ -1,52 +0,0 @@ -package Presenter.Algorithms; - -import Model.Line; -import Model.Point; - -import java.util.ArrayList; -import java.util.concurrent.ThreadLocalRandom; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 26.06.2017. - */ -public class RandomSampler { - - /** - * Diese Methode liefert eine r Elementige zufällige Stichprobe an Geraden. - * @param set Die gesammtmenge der Geraden aus denen gewählt werden soll - * @param r Anzahl der zu wählenden Geraden - * @return r Elementige zufällige Stichprobe an Geraden - */ - public static ArrayList run(ArrayList set, Double r, Integer indexOfEnd) { - - ArrayList sampledLines = new ArrayList<>(); - - for (int i = 0; i < r; i++) { - sampledLines.add(set.get(ThreadLocalRandom.current().nextInt(0, indexOfEnd))); - } - - return sampledLines; - } - - /** - * Diese Methode liefert eine r Elementige zufällige Stichprobe van Schnittpunkten. - * @param set Die gesammtmenge der Geraden aus denen gewählt werden soll - * @param r Anzahl der zu wählenden Geraden - * @return r Elementige zufällige Stichprobe an Schnittpunkten - */ - public static ArrayList run(ArrayList set, Double r) { - - ArrayList sampledLines = new ArrayList<>(); - Integer indexOfEnd = set.size(); - - for (int i = 0; i < r; i++) { - sampledLines.add(set.get(ThreadLocalRandom.current().nextInt(0, indexOfEnd)).getX()); - } - - return sampledLines; - } -} diff --git a/src/main/java/Presenter/Algorithms/RepeatedMedianEstimator.java b/src/main/java/Presenter/Algorithms/RepeatedMedianEstimator.java deleted file mode 100644 index ab8e4d6..0000000 --- a/src/main/java/Presenter/Algorithms/RepeatedMedianEstimator.java +++ /dev/null @@ -1,459 +0,0 @@ -package Presenter.Algorithms; - -import Model.Interval; -import Model.Line; -import Presenter.*; - -import java.util.*; -import java.util.concurrent.ThreadLocalRandom; - - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 28.05.2017. - */ -public class RepeatedMedianEstimator extends Observable implements Algorithm { - - private Presenter presenter; - private LinkedList set; - private HashMap> linePairs; - private HashMap medianIntersections = new HashMap<>(); - private HashMap> intersectionAbscissas = new HashMap<>(); - private Interval interval; - - //in der Literatur als L_i, C_i, und R_i bekannt - private ArrayList countLeftSlab; - private ArrayList countCenterSlab; - private ArrayList countRightSlab; - - //die Mengen L,C und R - private ArrayList linesInLeftSlab; - private ArrayList linesInCenterSlab; - private ArrayList linesInRightSlab; - - private Double r; - private Integer n; - private Double k; - private Double kLow; - private Double kHigh; - private Double beta; - - private Double thetaLow; - private Double thetaHigh; - - private Double slope; - private Double yInterception; - - - public RepeatedMedianEstimator(LinkedList set, Presenter presenter) { - this.set = set; - this.presenter = presenter; - interval = new Interval(-10000, 10000); - n = set.size(); - beta = 0.5; - countLeftSlab = new ArrayList<>(); - countCenterSlab = new ArrayList<>(); - countRightSlab = new ArrayList<>(); - - for (int i = 0; i < n; i++) { - countLeftSlab.add(0d); - countRightSlab.add(0d); - countCenterSlab.add(n - 1.0); - intersectionAbscissas.put(set.get(i), new ArrayList<>()); - } - - linesInLeftSlab = new ArrayList<>(); - linesInCenterSlab = new ArrayList<>(set); - linesInRightSlab = new ArrayList<>(); - linePairs = new HashMap<>(); - } - - public RepeatedMedianEstimator(LinkedList set) { - this(set,null); - } - - /** - * - */ - public void run() { - - while (linesInCenterSlab.size() != 1) { - n = linesInCenterSlab.size(); - r = Math.ceil(Math.pow(n, beta)); - ArrayList lines = RandomSampler.run(linesInCenterSlab, r, linesInCenterSlab.size()); - - - //For each Sampled Line, compute its median intersection abscissa - ArrayList medianIntersectionAbscissas = new ArrayList<>(); - for (Line l : lines) { - Double abscissa = estimateMedianIntersectionAbscissas(l); - medianIntersections.put(l, abscissa); - medianIntersectionAbscissas.add(abscissa); - } - - //rank of the repeated median in C - k = Math.max(1,Math.min(set.size(),(Math.ceil(n * 0.5) - linesInLeftSlab.size()))); - - //compute k_lo and k_hi - computeSlabBorders(); - - - // if (medianIntersectionAbscissas.size() < kLow || medianIntersectionAbscissas.size() sampleLines(ArrayList set, Double r) { - - ArrayList sampledLines = new ArrayList<>(); - - for (int i = 0; i < r; i++) { - sampledLines.add(set.get(ThreadLocalRandom.current().nextInt(0, linesInCenterSlab.size()))); - } - - return sampledLines; - } - - /** - * - * @param sampledLine - * @return - */ - public Double estimateMedianIntersectionAbscissas(Line sampledLine) { - - Integer index = Integer.parseInt(sampledLine.getId()); - ArrayList intersections = new ArrayList<>(); - double intersection; - - IntersectionCounter intersectionCounter = new IntersectionCounter(); - intersections = intersectionCounter.calculateIntersectionAbscissas(linesInCenterSlab, sampledLine); - - //Collections.sort(intersections); - //double ki = Math.ceil((n - 1) / 2) - countLeftSlab.get(index); - //double i = (Math.ceil((Math.sqrt(n) * ki) / countCenterSlab.get(index))); - double ki = Math.ceil((n - 1) / 2) - FastElementSelector.randomizedSelect(countLeftSlab, index); - double i = (Math.ceil((Math.sqrt(n) * ki) / FastElementSelector.randomizedSelect(countCenterSlab, index))); - int accessIndex; - if (i < 0) - accessIndex = 0; - else if (i >= intersections.size()) - accessIndex = intersections.size()-1; - else - accessIndex = (int) i; - - //System.out.println(accessIndex); - - //return intersections.get(accessIndex); - return FastElementSelector.randomizedSelect(intersections, accessIndex); - } - - /** - * - */ - public void computeSlabBorders() { - kLow = Math - .max(1, Math.floor( - ( (r * k) / (linesInCenterSlab.size())) - - ( (3 * Math.sqrt(r)) / (2)) - ) - ); - kHigh = Math - .min(r, Math.floor( - ((r * k) / (linesInCenterSlab.size())) - + ((3 * Math.sqrt(r)) / (2)) - ) - ); - } - - - - /** - * - */ - public void countNumberOfIntersectionsAbscissas() { - - for (Line line : linesInCenterSlab) { - ArrayList intersections = intersectionAbscissas.get(line); - Integer index = Integer.parseInt(line.getId()); - int left = 0; - int center = 0; - int right = 0; - - for (Double intersection : intersections) { - if (intersection <= thetaLow) { - left++; - } else if (intersection > thetaLow && intersection <= thetaHigh) { - center++; - } else if (intersection > thetaHigh){ - right++; - } - } - - //System.out.println("Linie: "+line.getId()+"\tLeft: "+left+"\t Center: "+center+"\t Right: "+right); - countLeftSlab.set(index, (double) left); - countCenterSlab.set(index, (double) center); - countRightSlab.set(index, (double) right); - } - - } - - /** - * - */ - public void contractIntervals() { - for (int i = 0; i < linesInCenterSlab.size(); i++) { - - double left = countLeftSlab.get(i); - double center = countCenterSlab.get(i); - double right = countRightSlab.get(i); - - double max = Math.max(left, Math.max(center, right)); - - if (left == max){ - linesInLeftSlab.add(linesInCenterSlab.get(i)); - linesInCenterSlab.remove(i); - } else if (right == max) { - linesInRightSlab.add(linesInCenterSlab.get(i)); - linesInCenterSlab.remove(i); - } - // if (medianIntersections.get(linesInCenterSlab.get(i)) != null) { - // if (medianIntersections.get(linesInCenterSlab.get(i)) <= thetaLow) { - // linesInLeftSlab.add(linesInCenterSlab.get(i)); - // linesInCenterSlab.remove(i); - // countLeftSlab.set(i, countLeftSlab.get(i) + 1); - // countCenterSlab.set(i, countCenterSlab.get(i) - 1); - // } else if (medianIntersections.get(linesInCenterSlab.get(i)) > thetaHigh) { - // linesInRightSlab.add(linesInCenterSlab.get(i)); - // linesInCenterSlab.remove(i); - // countRightSlab.set(i, countRightSlab.get(i) + 1); - // countCenterSlab.set(i, countCenterSlab.get(i) - 1); - // } - // } - // } - // - } - - //wähle C als C - if (linesInLeftSlab.size() < Math.ceil(n/2) && Math.ceil(n/2) <= linesInLeftSlab.size()+linesInCenterSlab.size()){ - interval.setLower(thetaLow + 0.1); - interval.setUpper(thetaHigh); - } - // wähle L als C - else if (Math.ceil(n/2) <= linesInLeftSlab.size()){ - interval.setUpper(thetaLow); - } - //wähle R als C - else if (linesInLeftSlab.size()+linesInCenterSlab.size() < Math.ceil(n/2) && Math.ceil(n/2) <= (linesInLeftSlab.size()+linesInCenterSlab.size()+linesInRightSlab.size()) ){ - interval.setLower(thetaHigh - 0.1); - } - } - - @Override - public void getResult() { - if (presenter != null) { - setChanged(); - double m = thetaLow; - double b = (-1)*( - (linesInCenterSlab.get(0).getM() * (thetaLow)) + linesInCenterSlab.get(0) - .getB()); - - slope = m; - yInterception = b; - String[] result = new String[]{"rm", m+"", b+""}; - notifyObservers(result); - }else { - double m = thetaLow; - double b = (-1)*((linesInCenterSlab.get(0).getM() * (thetaLow)) + linesInCenterSlab.get(0).getB()); - slope = m; - yInterception = b; - } - } - - /******************************************************************************************************************* - * Getter und Setter Methoden - ******************************************************************************************************************/ - public LinkedList getSet() { - return set; - } - - public void setSet(LinkedList set) { - this.set = set; - } - - public HashMap> getLinePairs() { - return linePairs; - } - - public void setLinePairs(HashMap> linePairs) { - this.linePairs = linePairs; - } - - public HashMap getMedianIntersections() { - return medianIntersections; - } - - public void setMedianIntersections(HashMap medianIntersections) { - this.medianIntersections = medianIntersections; - } - - public HashMap> getIntersectionAbscissas() { - return intersectionAbscissas; - } - - public void setIntersectionAbscissas( - HashMap> intersectionAbscissas) { - this.intersectionAbscissas = intersectionAbscissas; - } - - public Interval getInterval() { - return interval; - } - - public void setInterval(Interval interval) { - this.interval = interval; - } - - public ArrayList getCountLeftSlab() { - return countLeftSlab; - } - - public void setCountLeftSlab(ArrayList countLeftSlab) { - this.countLeftSlab = countLeftSlab; - } - - public ArrayList getCountCenterSlab() { - return countCenterSlab; - } - - public void setCountCenterSlab(ArrayList countCenterSlab) { - this.countCenterSlab = countCenterSlab; - } - - public ArrayList getCountRightSlab() { - return countRightSlab; - } - - public void setCountRightSlab(ArrayList countRightSlab) { - this.countRightSlab = countRightSlab; - } - - public ArrayList getLinesInLeftSlab() { - return linesInLeftSlab; - } - - public void setLinesInLeftSlab(ArrayList linesInLeftSlab) { - this.linesInLeftSlab = linesInLeftSlab; - } - - public ArrayList getLinesInCenterSlab() { - return linesInCenterSlab; - } - - public void setLinesInCenterSlab(ArrayList linesInCenterSlab) { - this.linesInCenterSlab = linesInCenterSlab; - } - - public ArrayList getLinesInRightSlab() { - return linesInRightSlab; - } - - public void setLinesInRightSlab(ArrayList linesInRightSlab) { - this.linesInRightSlab = linesInRightSlab; - } - - public Double getR() { - return r; - } - - public void setR(Double r) { - this.r = r; - } - - public Integer getN() { - return n; - } - - public void setN(Integer n) { - this.n = n; - } - - public Double getK() { - return k; - } - - public void setK(Double k) { - this.k = k; - } - - public Double getkLow() { - return kLow; - } - - public void setkLow(Double kLow) { - this.kLow = kLow; - } - - public Double getkHigh() { - return kHigh; - } - - public void setkHigh(Double kHigh) { - this.kHigh = kHigh; - } - - public Double getBeta() { - return beta; - } - - public void setBeta(Double beta) { - this.beta = beta; - } - - public Double getThetaLow() { - return thetaLow; - } - - public void setThetaLow(Double thetaLow) { - this.thetaLow = thetaLow; - } - - public Double getThetaHigh() { - return thetaHigh; - } - - public void setThetaHigh(Double thetaHigh) { - this.thetaHigh = thetaHigh; - } - - public Double getSlope() { - return slope; - } - - public Double getyInterception() { - return yInterception; - } -} - - diff --git a/src/main/java/Presenter/Evaluation/PercentageErrorBasedMeasure.java b/src/main/java/Presenter/Evaluation/PercentageErrorBasedMeasure.java deleted file mode 100644 index 5323a53..0000000 --- a/src/main/java/Presenter/Evaluation/PercentageErrorBasedMeasure.java +++ /dev/null @@ -1,82 +0,0 @@ -package Presenter.Evaluation; - -import Model.Line; -import Presenter.Algorithms.FastElementSelector; -import java.util.ArrayList; -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: 07.09.2017. - */ -public class PercentageErrorBasedMeasure { - - - private ArrayList percentageError; - - public PercentageErrorBasedMeasure(final LinkedList lines, Double m, Double b){ - - ArrayList sampson = new ArrayList<>(); - - for (Line line : lines) { - Double e = Math.pow(m * line.getM() - line.getB() + b, 2) / (Math.pow(m, 2) + 1); - sampson.add(e); - } - - percentageError = new ArrayList<>(); - - for (int j=0;j abs = new ArrayList<>(); - - for (Double d : percentageError){ - abs.add(Math.abs(d)); - } - - return FastElementSelector.randomizedSelect(abs, abs.size() * 0.5); - } - - public Double rmspe(){ - double error = 0; - - for (Double d : percentageError) { - error += Math.pow(d, 2); - } - - error /= percentageError.size(); - - return Math.sqrt(error); - } - - public Double rmdspe(){ - ArrayList squares = new ArrayList(); - for (Double d : percentageError){ - squares.add(Math.pow(d,2)); - } - - return Math.sqrt(FastElementSelector.randomizedSelect(squares, squares.size() * 0.5)); - } -} diff --git a/src/main/java/Presenter/Evaluation/ScaleDependentMeasure.java b/src/main/java/Presenter/Evaluation/ScaleDependentMeasure.java deleted file mode 100644 index 00256db..0000000 --- a/src/main/java/Presenter/Evaluation/ScaleDependentMeasure.java +++ /dev/null @@ -1,60 +0,0 @@ -package Presenter.Evaluation; - -import Model.Line; -import Presenter.Algorithms.FastElementSelector; -import java.util.ArrayList; -import java.util.LinkedList; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 07.09.2017. - */ -public class ScaleDependentMeasure { - - private ArrayList errorValues; - - public ScaleDependentMeasure(final LinkedList lines, Double m, Double b){ - //Liste mit den Fehler zu jedem Punkt - errorValues = new ArrayList<>(); - - for (Line line : lines) { - Double e = Math.pow(m * line.getM() - line.getB() + b, 2) / (Math.pow(m, 2) + 1); - errorValues.add(e); - } - } - - /* Skalierungs Abhängige Approximationsgüten */ - //unterschiedliche Alg.- auf einem Datensatz - public Double mse() { - double error = 0; - - for (Double d : errorValues) { - error += Math.pow(d, 2); - } - - error /= errorValues.size(); - - return error; - } - - public Double rmse() { - return Math.sqrt(mse()); - } - - public Double mae() { - double error = 0; - for (Double d : errorValues) { - error += Math.abs(d); - } - error /= errorValues.size(); - return error; - } - - public Double mdae() { - return FastElementSelector - .randomizedSelect(errorValues, errorValues.size() * 0.5); - } -} diff --git a/src/main/java/Presenter/Evaluation/ScaledErrorBasedMeasure.java b/src/main/java/Presenter/Evaluation/ScaledErrorBasedMeasure.java deleted file mode 100644 index 93a9bf3..0000000 --- a/src/main/java/Presenter/Evaluation/ScaledErrorBasedMeasure.java +++ /dev/null @@ -1,71 +0,0 @@ -package Presenter.Evaluation; - -import Model.Line; -import Presenter.Algorithms.FastElementSelector; -import java.util.ArrayList; -import java.util.LinkedList; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 07.09.2017. - */ -public class ScaledErrorBasedMeasure { - - - private ArrayList scaledError; - - public ScaledErrorBasedMeasure(final LinkedList lines, Double m, Double b){ - //Liste mit den Fehler zu jedem Punkt - ArrayList sampson = new ArrayList<>(); - - - Double denum = 0d; - for (int i=2;i lines = reader.readAll(); - int counter = 0; - String[] result = {"import", lines.size()+"", ""}; - //System.out.println("+-------------------------------------------------------------------------------+"); - for(String[] nextLine : lines) { - // nextLine[] is an array of values from the line - Double x = Double.parseDouble(nextLine[1]); - Double y = Double.parseDouble(nextLine[2]) * (-1); - Line line = new Line(x,y); - line.setId(counter+""); - this.presenter.getModel().addLine(line); - //System.out.format("|\t\t\t\t\t %-11d \t|\t\t\t\t\t %-11f \t|\t\t\t\t\t %-11f \t\t\t\t\t|\n", id,x,y); - setChanged(); - counter++; - result[2] = counter + ""; - Thread.sleep(1); - notifyObservers(result); - } - - //System.out.println("+-------------------------------------------------------------------------------+"); - } catch (IOException e) { - e.printStackTrace(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - -} diff --git a/src/main/java/Presenter/ImportExport/EvalResultLatexExport.java b/src/main/java/Presenter/ImportExport/EvalResultLatexExport.java deleted file mode 100644 index 8307488..0000000 --- a/src/main/java/Presenter/ImportExport/EvalResultLatexExport.java +++ /dev/null @@ -1,98 +0,0 @@ -package Presenter.ImportExport; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import javax.swing.JOptionPane; -import javax.swing.SwingUtilities; -import javax.swing.table.DefaultTableModel; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 08.09.2017. - */ -public class EvalResultLatexExport { - - private DefaultTableModel model; - private File file; - - public EvalResultLatexExport(DefaultTableModel model, File file ) { - this.model = model; - this.file = file; - } - - /** - * e.g. Source: https://en.wikibooks.org/wiki/LaTeX/Tables - * \begin{tabular}{l*{3}{c}} - * Team & P & W & D & L & F & A & Pts \\\hline - * Manchester United & 6 & 4 & 0 & 2 & 10 & 5 & 12 \\ - * Celtic & 6 & 3 & 0 & 3 & 8 & 9 & 9 \\ - * Benfica & 6 & 2 & 1 & 3 & 7 & 8 & 7 \\ - * FC Copenhagen & 6 & 2 & 1 & 3 & 5 & 8 & 7 \\ - * \end{tabular} - * - * - * @return - */ - private String createOutputData(){ - String split = "&"; - StringBuilder doc = new StringBuilder(); - doc.append("\\begin{tabular}{l|*{3}{r}}"+"\r\n"); - for (int i=0;i 5) - doc.append("\\textsc{" + model.getColumnName(i) + "}"+split); - } - - doc.deleteCharAt(doc.lastIndexOf(split)); - doc.append("\\\\\\hline\\hline"+"\r\n"); - - for (int i=0;i{ - JOptionPane.showMessageDialog(null,"Export war Erfolgreich!"); - }); - - - } catch (IOException e) { - e.printStackTrace(); - } finally { - try { - bufferedWriter.close(); - fileWriter.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - } - -} diff --git a/src/main/java/Presenter/Presenter.java b/src/main/java/Presenter/Presenter.java deleted file mode 100644 index f5840fb..0000000 --- a/src/main/java/Presenter/Presenter.java +++ /dev/null @@ -1,384 +0,0 @@ -package Presenter; - -import Model.LineModel; -import Model.Interval; -import Model.Line; -import Presenter.Algorithms.IntersectionCounter; -import Presenter.Algorithms.LeastMedianOfSquaresEstimator; -import Presenter.Algorithms.RepeatedMedianEstimator; -import Presenter.Algorithms.TheilSenEstimator; -import Presenter.Evaluation.EvaluateAlgorithms; -import Presenter.Generator.DatasetGenerator; -import Presenter.ImportExport.DataExporter; -import Presenter.ImportExport.DataImporter; -import Presenter.ImportExport.EvalResultLatexExport; -import View.MainFrame; - -import javax.swing.*; -import java.io.File; -import java.util.LinkedList; -import java.util.List; -import java.util.Observable; -import java.util.Observer; -import javax.swing.table.DefaultTableModel; - - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 28.05.2017. - */ -public class Presenter implements Observer { - - private LineModel model; - private MainFrame view; - private EvaluateAlgorithms eval; - - /* Threads */ - private Thread tsThread; - private Thread rmThread; - private Thread lmsThread; - private Thread importThread; - private Thread exportThread; - private Thread exportResultThread; - private Thread generatorThread; - private Thread evalThread; - - public Presenter(LineModel model, MainFrame view) { - this.model = model; - this.view = view; - } - - - @Override - public void update(Observable o, Object arg) { - String[] result = ((String[]) arg); - - if (result[0] == "eval-dataset-generated"){ - SwingUtilities.invokeLater(() -> getView().addEvalDataset(eval.getData())); - } - - if (result[0] == "eval-d"){ - SwingUtilities.invokeLater(() -> getView().appendEvalResult(result,Integer.parseInt(result[1]),false)); - } - - if (result[0] == "eval-ds"){ - SwingUtilities.invokeLater(() -> getView().appendEvalResult(result)); - } - - if (result[0] == "eval-t"){ - SwingUtilities.invokeLater(() -> getView().appendEvalResult(result,Integer.parseInt(result[1]),true)); - } - - if (result[0] == "lines-res"){ - SwingUtilities.invokeLater(() -> getView().drawLineResult(result, Integer.parseInt(result[1]))); - } - - if (result[0] == "lines-res-mult"){ - SwingUtilities.invokeLater(() -> getView().drawLineResults(result)); - } - - if (result[0] == "lms"){ - SwingUtilities.invokeLater(() -> { - getView().visualizeLMS(Double.parseDouble(result[1]), Double.parseDouble(result[2])); - //getView().setLmsIsComplete(true); - getView().logHeading("Least Median of Squares"); - getView().log("m: " + result[1]); - getView().log("b: " + result[2]); - getView().logSuccess("Berechnung wurde Erfolgreich durchgeführt
"); - }); - } - - if (result[0] == "rm"){ - SwingUtilities.invokeLater(() -> { - getView().visualizeRM(Double.parseDouble(result[1]), Double.parseDouble(result[2])); - getView().logHeading("Repeated Median Estimator"); - getView().log("m: " + result[1]); - getView().log("b: " + result[2]); - getView().logSuccess("Berechnung wurde Erfolgreich durchgeführt
"); - }); - } - - if (result[0] == "ts"){ - SwingUtilities.invokeLater(() -> { - getView().visualizeTS(Double.parseDouble(result[1]), Double.parseDouble(result[2])); - getView().logHeading("Theil-Sen Estimator"); - getView().log("m: " + result[1]); - getView().log("b: " + result[2]); - getView().logSuccess("Berechnung wurde Erfolgreich durchgeführt
"); - }); - } - - if (result[0] == "import"){ - Double max = Double.parseDouble(result[1]); - Double current = Double.parseDouble(result[2]); - Integer progress = (int) (100 * (current/max)); - //100% erreicht - if (progress == 100){ - SwingUtilities.invokeLater(() -> { - getView().showImportProgress(progress); - getView().enableFunctionality(); - getView().getProgressDialog().dispose(); - }); - setup(); - Thread t = new Thread(() -> { - calculateIntersections(); - }); - t.start(); - try { - t.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } else { - SwingUtilities.invokeLater(() -> { - getView().showImportProgress(progress); - }); - } - } - if (result[0] == "export"){ - SwingUtilities.invokeLater(() -> { - getView().logSuccess("Export Erfolgreich"); - getView().log(result[1]+"
"); - }); - } - - if (result[0] == "generator"){ - SwingUtilities.invokeLater(() -> { - getView().logSuccess("Generierung Erfolgreich"); - getView().log(result[1]); - getView().log(result[2]); - getView().log(result[3] + "
"); - }); - } - } - - public void visualizeDualLines() { - view.createDualityDialog(); - } - - /*************************************************************************************************************************** - * Ausführung der Algorithmen - ***************************************************************************************************************************/ - public void calculateLMS(String[] input) { - if (input[0] != null && input[1] != null){ - if (lmsThread == null || !lmsThread.isAlive()){ - lmsThread = new Thread(() -> { - Double constant = Double.parseDouble(input[0]); - Double error = Double.parseDouble(input[1]); - LeastMedianOfSquaresEstimator lms = new LeastMedianOfSquaresEstimator(getModel().getLines(), getModel().getNodes(), this); - lms.setConstant(constant); - lms.setQuantileError(error); - lms.addObserver(this); - lms.run(); - lms.getResult(); - }); - lmsThread.start(); - try { - lmsThread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - } - - public void calculateRM(String input){ - if (input != null){ - if (rmThread == null || !rmThread.isAlive()){ - rmThread = new Thread(() -> { - RepeatedMedianEstimator rm = new RepeatedMedianEstimator(getModel().getLines(), this); - Double parameter = Double.parseDouble(input); - rm.setBeta(parameter); - rm.addObserver(this); - rm.run(); - rm.getResult(); - }); - rmThread.start(); - try { - rmThread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - } - - public void calculateTS(String input){ - if (input != null){ - if (tsThread == null || !tsThread.isAlive()){ - tsThread = new Thread(() ->{ - TheilSenEstimator ts = new TheilSenEstimator(getModel().getLines(), getModel().getNodes(),this); - ts.addObserver(this); - ts.run(); - ts.getResult(); - }); - tsThread.start(); - try { - tsThread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - } - - /*************************************************************************************************************************** - * Hilfsmethoden - ***************************************************************************************************************************/ - public void setup(){ - //Darstellung der Schnittpunkte in einer Tabelle - List heading = new LinkedList<>(); - List> rows = new LinkedList<>(); - heading.add("Geraden"); - for (int j = 0; j < getModel().getLines().size()-2; j++) { - LinkedList rowEntry = new LinkedList<>(); - Line p1 = getModel().getLines().get(j); - rowEntry.add("f(x) = " + p1.getM() + "x + " + p1.getB()); - - if (j+1 < getModel().getLines().size()){ - Line p2 = getModel().getLines().get(j+1); - rowEntry.add("f(x) = " + p2.getM() + "x + " + p2.getB()); - } - - if (j+2 < getModel().getLines().size()){ - Line p3 = getModel().getLines().get(j+2); - rowEntry.add("f(x) = " + p3.getM() + "x + " + p3.getB()); - } - rows.add(rowEntry); - } - getView().logHeading("Schnittpunkte der Dualen Geraden:"); - getView().createTable(heading, rows); - - getView().log("
"); - } - - public void calculateIntersections() { - try { - Thread thread = new Thread(() -> { - IntersectionCounter counter = new IntersectionCounter(); - counter.run(getLines(), new Interval(-99999,99999)); - counter.calculateIntersectionAbscissas(getModel()); - getModel().setXbounds(); - getModel().setYbounds(); - - }); - thread.start(); - thread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - public void startImport(File file){ - if (importThread == null || !importThread.isAlive()){ - importThread = new Thread(()->{ - DataImporter importer = new DataImporter(file, this); - importer.addObserver(this); - importer.run(); - }); - importThread.start(); - try { - importThread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - public void startExport(File file){ - if (exportThread == null || !exportThread.isAlive()){ - exportThread = new Thread(()->{ - DataExporter exporter = new DataExporter(getModel(), file); - exporter.addObserver(this); - exporter.export(); - }); - exportThread.start(); - try { - exportThread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - public void startResultExport(DefaultTableModel model, File file){ - if (exportResultThread == null || !exportResultThread.isAlive()){ - exportResultThread = new Thread(()->{ - EvalResultLatexExport exporter = new EvalResultLatexExport(model, file); - exporter.writeFile(); - }); - exportResultThread.start(); - try { - exportResultThread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - public void generateDataset(){ - if (generatorThread == null || !generatorThread.isAlive()){ - generatorThread = new Thread(() -> { - DatasetGenerator generator = new DatasetGenerator(); - generator.addObserver(this); - getModel().setLines(generator.generateCircle(100)); - calculateIntersections(); - getView().enableFunctionality(); - }); - generatorThread.start(); - try { - generatorThread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - public void startEvaluation(int typ, int n, int alg, String datasettyp){ - - if (evalThread == null || !evalThread.isAlive()){ - evalThread = new Thread(() ->{ - try { - eval = new EvaluateAlgorithms(typ,n,alg,datasettyp); - eval.addObserver(this); - eval.run(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - }); - evalThread.start(); - } - } - /*************************************************************************************************************************** - * Getter und Setter Methoden - ***************************************************************************************************************************/ - - - public LineModel getModel() { - return model; - } - - public void setModel(LineModel model) { - this.model = model; - } - - public MainFrame getView() { - return view; - } - - public void setView(MainFrame view) { - this.view = view; - } - - public LinkedList getLines() { - return this.model.getLines(); - } - - public void setLines(LinkedList lines) { - this.model.setLines(lines); - } - -} diff --git a/src/main/java/View/DualityDialog.java b/src/main/java/View/DualityDialog.java deleted file mode 100644 index 29f9261..0000000 --- a/src/main/java/View/DualityDialog.java +++ /dev/null @@ -1,232 +0,0 @@ -package View; - -import Model.Line; -import 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; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 28.05.2017. - */ -public class DualityDialog extends JPanel { - - private LinkedList lines; - private LinkedList 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; - - public DualityDialog() { - super(); - this.setPreferredSize(new Dimension(800, 800)); - this.setMinimumSize(new Dimension(800, 800)); - this.setLayout(new BorderLayout()); - } - - public void setPrameters(LinkedList lines, LinkedList 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; - } - - 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.setText("Um in dem Plot hineinzuzoomen kann das Mausrad verwendett werden. \nUm sich anschließen vertikal bzw. horizontal zu bewegen kann die Kombination (Umschalt/Steuerung)\nund Mausrad verwendett werden."); - Font font = new Font("Serif", Font.ITALIC, 12); - info.setFont(font); - info.setForeground(Color.DARK_GRAY); - info.setEditable(false); - info.setWrapStyleWord(true); - - this.add(info, BorderLayout.SOUTH); - this.add(panel, BorderLayout.CENTER); - } - - 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; - } - } - }); - } - - protected void addZooming(ChartPanel chartPanel) { - - chartPanel.addMouseWheelListener(new MouseWheelListener() { - - public void mouseWheelMoved(MouseWheelEvent e) { - - Double min; - Double max; - Double val = e.getPreciseWheelRotation() * -1; - - if(ctrlPressed == true){ - //System.out.println("CTRL + ZOOM"); - min = range.getLowerBound(); - max = range.getUpperBound(); - DateRange dateRangeX = move(val, min, max); - range.setRange(dateRangeX); - } else if (shiftPressed == true){ - //System.out.println("SHIFT + ZOOM"); - min = domain.getLowerBound(); - max = domain.getUpperBound(); - DateRange dateRangeY = move(val, min, max); - domain.setRange(dateRangeY); - } else { - 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); - } - - } - - 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); - } - - 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); - } - - } - }); - } - - public void clear(){ - if (dataset != null) - dataset.removeAllSeries(); - } - - } \ No newline at end of file diff --git a/src/main/java/View/MainFrame.java b/src/main/java/View/MainFrame.java deleted file mode 100644 index ba744ee..0000000 --- a/src/main/java/View/MainFrame.java +++ /dev/null @@ -1,604 +0,0 @@ -package View; - - -import Model.Line; -import Presenter.Presenter; -import View.Panels.*; - -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.LinkedList; -import javax.imageio.ImageIO; -import javax.swing.*; -import javax.swing.filechooser.FileNameExtensionFilter; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.io.File; -import java.io.IOException; -import java.util.Arrays; -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 MainFrame extends JFrame { - - private Presenter presenter; - private Boolean lmsIsComplete = false; - private Boolean rmIsComplete = false; - private Boolean tsIsComplete = false; - - private JButton arrangementButton; - private JButton importButton; - private JButton generateButton; - private JButton exportButton; - - private OutputPanel output; - private MenuPanel menupanel; - private LMSPanel lmsPanel; - private RMPanel rmPanel; - private TSPanel tsPanel; - private JPanel pane; - private JPanel northPanel; - - private DualityDialog arrangement; - private JDialog arrangementDialog; - private PlotDialog plotLMS; - private PlotDialog plotRM; - private PlotDialog plotTS; - private JDialog progressDialog; - private JDialog evaluationDialog; - - private Container progressContent; - private JProgressBar progressBar; - - - - private JSplitPane splitpane; - private JScrollPane scrollPane; - private JTabbedPane tabbedPane; - private EvaluationPanel evaluationPanel; - - public MainFrame() { - initializeComponents(); - setDimensions(); - setLayouts(); - setTitles(); - - addComponents(); - - setCloseOperations(); - setActionListeners(); - setIcons(); - disableFunctionality(); - this.setVisible(true); - } - - - /******************************************************************************************************************* - * visualisierungs methoden - ******************************************************************************************************************/ - - public void createDualityDialog() { - arrangement = new DualityDialog(); - arrangementDialog = new JDialog(); - arrangementDialog.setTitle("Dual Representation - Dialog"); - arrangementDialog.setSize(new Dimension(800, 800)); - arrangementDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); - arrangement.clear(); - arrangement.setPrameters(getPresenter().getLines(), - getPresenter().getModel().getNodes(), - getPresenter().getModel().getxMinimum(), - getPresenter().getModel().getxMaximum(), - getPresenter().getModel().getyMinimum(), - getPresenter().getModel().getyMaximum()); - arrangement.createArrangement(); - - SwingUtilities.invokeLater(() -> { - arrangementDialog.add(arrangement); - arrangementDialog.revalidate(); - arrangementDialog.repaint(); - arrangementDialog.setVisible(true); - }); - } - - public void visualizeLMS(double m, double b) { - plotLMS = new PlotDialog(); - lmsPanel.setPlotDialog(plotLMS); - createPlot(m,b,plotLMS,lmsPanel, "LMS"); - } - - public void visualizeRM(double m, double b) { - plotRM = new PlotDialog(); - rmPanel.setPlotDialog(plotRM); - createPlot(m,b,plotRM,rmPanel, "RM"); - } - - public void visualizeTS(double m, double b){ - plotTS = new PlotDialog(); - tsPanel.setPlotDialog(plotTS); - createPlot(m,b,plotTS, tsPanel, "TS"); - } - - public void createPlot(double m, double b, PlotDialog plot, JPanel panel, String name){ - SwingUtilities.invokeLater(() -> { - plot.clear(); - plot.createPlot(getPresenter().getLines()); - plot.addLineToPlot(m, b, name); - panel.revalidate(); - }); - } - - public void showImportProgress(Integer progress){ - progressBar.setValue(progress); - progressBar.setStringPainted(true); - progressDialog.setVisible(true); - } - - public void showEvauluationDialog(){ - if (evaluationDialog == null){ - SwingUtilities.invokeLater(() -> { - evaluationDialog = new JDialog(); - evaluationDialog.setTitle("Evaluation"); - evaluationDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); - evaluationDialog.setSize(1800,800); - evaluationDialog.setLocationRelativeTo(null); - - evaluationPanel = new EvaluationPanel(this); - evaluationDialog.add(evaluationPanel); - evaluationDialog.setVisible(true); - }); - } else { - SwingUtilities.invokeLater(()->{ - evaluationDialog.setVisible(true); - }); - } - - } - - public void appendEvalResult(Object[] res,int col, boolean isApprCol){ - SwingUtilities.invokeLater(() -> { - Object[] tmp = Arrays.asList(res).subList(2,res.length).toArray(); - if (isApprCol){ - evaluationPanel.setCurrentRow(tmp.length); - evaluationPanel.addColumn(tmp, col,true); - } else { - evaluationPanel.addColumn(tmp, col+1, false); - } - evaluationPanel.repaint(); - evaluationPanel.revalidate(); - }); - } - public void appendEvalResult(Object[] res){ - SwingUtilities.invokeLater(() -> { - Object[] tmp = Arrays.asList(res).subList(1,res.length).toArray(); - evaluationPanel.addRow(tmp); - evaluationPanel.repaint(); - evaluationPanel.revalidate(); - }); - } - - public void drawLineResult(Object[] res, int alg){ - SwingUtilities.invokeLater(() -> { - Object[] result = Arrays.asList(res).subList(2,res.length).toArray(); - evaluationPanel.drawLines(result, alg); - evaluationPanel.repaint(); - evaluationPanel.revalidate(); - }); - } - - public void drawLineResults(Object[] res){ - SwingUtilities.invokeLater(() -> { - Object[] result = Arrays.asList(res).subList(1,res.length).toArray(); - ArrayList algs = new ArrayList<>(); - - for (int i=0;i< (result.length+1) / 3;i++){ - String name = (String) result[(3*i)]; - String m = (String) result[(3*i)+1]; - String b = (String) result[(3*i)+2]; - Double[] tmp = {Double.parseDouble(name), Double.parseDouble(m), Double.parseDouble(b)}; - algs.add(tmp); - } - - evaluationPanel.drawLines(algs); - evaluationPanel.repaint(); - evaluationPanel.revalidate(); - }); - } - - public void addEvalDataset(LinkedList lines){ - SwingUtilities.invokeLater(() -> { - evaluationPanel.setDualPoints(lines); - evaluationPanel.repaint(); - evaluationPanel.revalidate(); - }); - } - - - /******************************************************************************************************************* - * init GUI - ******************************************************************************************************************/ - private void setTitles() { - this.setTitle("Algorithmen zur Berechnung von Ausgleichgeraden"); - importButton.setText("Import"); - exportButton.setText("Export"); - generateButton.setText("Generiere"); - arrangementButton.setText("Dualraum"); - } - - private void setupTabbedPane() { - tabbedPane.add("Least Median of Squares", lmsPanel); - tabbedPane.add("Repeated Median", rmPanel); - tabbedPane.add("Theil-Sen", tsPanel); - } - - private void addComponents() { - pane.add(arrangementButton); - pane.add(importButton); - pane.add(exportButton); - pane.add(generateButton); - - northPanel.add(menupanel); - northPanel.add(pane); - - setupSplitPane(); - setupTabbedPane(); - - progressContent.add(progressBar, BorderLayout.NORTH); - progressBar.setBorder(BorderFactory.createTitledBorder("Import...")); - - this.add(northPanel, BorderLayout.NORTH); - this.add(splitpane, BorderLayout.CENTER); - - } - - private void setupSplitPane() { - splitpane.setOrientation(JSplitPane.HORIZONTAL_SPLIT); - splitpane.setResizeWeight(.5d); - splitpane.setContinuousLayout(true); - splitpane.setLeftComponent(output); - splitpane.setRightComponent(tabbedPane); - } - - private void setCloseOperations() { - this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - progressDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); - } - - private void setDimensions() { - this.setExtendedState(JFrame.MAXIMIZED_BOTH); - this.setResizable(false); - GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); - this.setMaximizedBounds(env.getMaximumWindowBounds()); - lmsPanel.setMinimumSize(new Dimension(400, 500)); - rmPanel.setMinimumSize(new Dimension(400, 500)); - tsPanel.setMinimumSize(new Dimension(400, 500)); - output.setMinimumSize(new Dimension(400, 500)); - progressDialog.setSize(300, 80); - progressDialog.setResizable(false); - } - - private void setLayouts() { - this.setLayout(new BorderLayout()); - pane.setLayout(new FlowLayout(FlowLayout.LEFT)); - northPanel.setLayout(new BoxLayout(northPanel, BoxLayout.Y_AXIS)); - } - - private void initializeComponents() { - //Panels - pane = new JPanel(); - lmsPanel = new LMSPanel(); - rmPanel = new RMPanel(); - tsPanel = new TSPanel(); - menupanel = new MenuPanel(this); - northPanel = new JPanel(); - - //Dialogs - progressDialog = new JDialog(); - progressDialog.setLocationRelativeTo(null); - progressContent = progressDialog.getContentPane(); - progressBar = new JProgressBar(); - - //Panes - tabbedPane = new JTabbedPane(); - output = new OutputPanel(); - splitpane = new JSplitPane(); - - //Buttons - arrangementButton = new JButton(); - importButton = new JButton(); - generateButton = new JButton(); - exportButton = new JButton(); - } - - private void setIcons(){ - try { - ClassLoader classLoader = getClass().getClassLoader(); - Image imgImport = ImageIO.read(classLoader.getResource("import.png")).getScaledInstance(16,16,Image.SCALE_SMOOTH); - Image imgPlot = ImageIO.read(classLoader.getResource("plot.png")).getScaledInstance(16,16,Image.SCALE_SMOOTH); - Image imgStart = ImageIO.read(classLoader.getResource("start.png")).getScaledInstance(32,32,Image.SCALE_SMOOTH); - Image imgGenerate = ImageIO.read(classLoader.getResource("generate.png")).getScaledInstance(16,16,Image.SCALE_SMOOTH); - Image imgExport = ImageIO.read(classLoader.getResource("export.png")).getScaledInstance(16,16,Image.SCALE_SMOOTH); - Image imgFrame = ImageIO.read(classLoader.getResource("frame.png")).getScaledInstance(32,23,Image.SCALE_SMOOTH); - - - importButton.setIcon(new ImageIcon(imgImport)); - exportButton.setIcon(new ImageIcon(imgExport)); - generateButton.setIcon(new ImageIcon(imgGenerate)); - arrangementButton.setIcon(new ImageIcon(imgPlot)); - lmsPanel.getStartButton().setIcon(new ImageIcon(imgStart)); - rmPanel.getStartButton().setIcon(new ImageIcon(imgStart)); - tsPanel.getStartButton().setIcon(new ImageIcon(imgStart)); - this.setIconImage(imgFrame); - } catch (IOException e) { - e.printStackTrace(); - } - } - - private void setActionListeners() { - arrangementButton.addActionListener((ActionEvent e) -> { - Thread t = new Thread(() -> getPresenter().visualizeDualLines()); - t.start(); - }); - - lmsPanel.getStartButton().addActionListener((ActionEvent e) -> { - if (lmsPanel.getInput() != null){ - Thread t = new Thread( - () -> this.getPresenter().calculateLMS(lmsPanel.getInput())); - t.start(); - } - }); - - rmPanel.getStartButton().addActionListener((ActionEvent e) -> { - if (rmPanel.getInput() != null){ - Thread t = new Thread( - () -> this.getPresenter().calculateRM(rmPanel.getInput())); - t.start(); - } - }); - - tsPanel.getStartButton().addActionListener((ActionEvent e) -> { - Thread t = new Thread( - () -> this.getPresenter().calculateTS("")); - t.start(); - }); - - importButton.addActionListener((ActionEvent e) -> { - SwingUtilities.invokeLater(() -> { - File file = null; - JFileChooser chooser = new JFileChooser(); - chooser.setPreferredSize(new Dimension(800,700)); - File workingDirectory = new File(System.getProperty("user.dir")); - chooser.setCurrentDirectory(workingDirectory); - chooser.setFileFilter(new FileNameExtensionFilter("Comma-Separated Value", "csv", "text")); - - chooser.setMultiSelectionEnabled(false); - chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); - - - if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION){ - //System.out.println ("Datei "+chooser.getSelectedFile()+ " ausgewählt."); - file = chooser.getSelectedFile(); - final File input = file; - Thread t = new Thread(() -> this.getPresenter().startImport(input)); - t.start(); - } - }); - }); - - exportButton.addActionListener((ActionEvent e) -> { - SwingUtilities.invokeLater(() -> { - File file = null; - JFileChooser chooser = new JFileChooser(); - chooser.setPreferredSize(new Dimension(800,700)); - File workingDirectory = new File(System.getProperty("user.dir")); - chooser.setCurrentDirectory(workingDirectory); - chooser.setFileFilter(new FileNameExtensionFilter("Comma-Separated Value", "csv", "text")); - - chooser.setMultiSelectionEnabled(false); - chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); - - - if (chooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION){ - //System.out.println ("Datei "+chooser.getSelectedFile()+ " ausgewählt."); - file = chooser.getSelectedFile(); - String filename = file.getAbsolutePath().contains(".csv") ? file.getAbsolutePath() : file.getAbsolutePath().concat(".csv"); - File withExtension = new File(filename); - final File input = withExtension; - Thread t = new Thread(() -> this.getPresenter().startExport(input)); - t.start(); - } - }); - }); - - generateButton.addActionListener((ActionEvent e) -> { - SwingUtilities.invokeLater(() -> { - getPresenter().generateDataset(); - }); - }); - - } - - public void enableFunctionality(){ - this.getLmsPanel().getStartButton().setEnabled(true); - this.getRmPanel().getStartButton().setEnabled(true); - this.getTsPanel().getStartButton().setEnabled(true); - this.getArrangementButton().setEnabled(true); - this.getExportButton().setEnabled(true); - } - - public void disableFunctionality(){ - this.getLmsPanel().getStartButton().setEnabled(false); - this.getRmPanel().getStartButton().setEnabled(false); - this.getTsPanel().getStartButton().setEnabled(false); - this.getArrangementButton().setEnabled(false); - this.getExportButton().setEnabled(false); - } - - /******************************************************************************************************************* - * log Methode - ******************************************************************************************************************/ - public void log(String s) { - SwingUtilities.invokeLater(() -> output.appendParagraph(s)); - } - - public void logError(String s) { - SwingUtilities.invokeLater(() -> output.appendParagraphRed(s)); - } - - public void logSuccess(String s) { - SwingUtilities.invokeLater(() -> output.appendParagraphGreen(s)); - } - - public void logHeading(String s) { - SwingUtilities.invokeLater(() -> output.appendParagraphWithHeading(s)); - } - - public void createTable(List heading, List> rows) { - SwingUtilities.invokeLater(() -> output.logTable(heading, rows)); - } - - /******************************************************************************************************************* - * Getter und Setter Methoden - ******************************************************************************************************************/ - - public Boolean getLmsIsComplete() { - return lmsIsComplete; - } - - public void setLmsIsComplete(Boolean lmsIsComplete) { - this.lmsIsComplete = lmsIsComplete; - } - - public Boolean getRmIsComplete() { - return rmIsComplete; - } - - public void setRmIsComplete(Boolean rmIsComplete) { - this.rmIsComplete = rmIsComplete; - } - - public Boolean getTsIsComplete() { - return tsIsComplete; - } - - public void setTsIsComplete(Boolean tsIsComplete) { - this.tsIsComplete = tsIsComplete; - } - - public JButton getArrangementButton() { - return arrangementButton; - } - - public void setArrangementButton(JButton arrangementButton) { - this.arrangementButton = arrangementButton; - } - - public JButton getImportButton() { - return importButton; - } - - public void setImportButton(JButton importButton) { - this.importButton = importButton; - } - - public JPanel getPane() { - return pane; - } - - public void setPane(JPanel pane) { - this.pane = pane; - } - - public JDialog getArrangementDialog() { - return arrangementDialog; - } - - public void setArrangementDialog(JDialog arrangementDialog) { - this.arrangementDialog = arrangementDialog; - } - - public OutputPanel getOutput() { - return output; - } - - public void setOutput(OutputPanel output) { - this.output = output; - } - - public MenuPanel getMenupanel() { - return menupanel; - } - - public LMSPanel getLmsPanel() { - return lmsPanel; - } - - public JSplitPane getSplitpane() { - return splitpane; - } - - public void setSplitpane(JSplitPane splitpane) { - this.splitpane = splitpane; - } - - public JScrollPane getScrollPane() { - return scrollPane; - } - - public void setScrollPane(JScrollPane scrollPane) { - this.scrollPane = scrollPane; - } - - public RMPanel getRmPanel() { - return rmPanel; - } - - public void setRmPanel(RMPanel rmPanel) { - this.rmPanel = rmPanel; - } - - public PlotDialog getPlotLMS() { - return plotLMS; - } - - public void setPlotLMS(PlotDialog plotLMS) { - this.plotLMS = plotLMS; - } - - public Presenter getPresenter() { - return presenter; - } - - public void setPresenter(Presenter presenter) { - this.presenter = presenter; - } - - public JDialog getProgressDialog() { - return progressDialog; - } - - public void setProgressDialog(JDialog progressDialog) { - this.progressDialog = progressDialog; - } - - public TSPanel getTsPanel() { - return tsPanel; - } - - public void setTsPanel(TSPanel tsPanel) { - this.tsPanel = tsPanel; - } - - public JButton getExportButton() { - return exportButton; - } - - public void setExportButton(JButton exportButton) { - this.exportButton = exportButton; - } -} diff --git a/src/main/java/View/Panels/LMSPanel.java b/src/main/java/View/Panels/LMSPanel.java deleted file mode 100644 index dd03ab6..0000000 --- a/src/main/java/View/Panels/LMSPanel.java +++ /dev/null @@ -1,153 +0,0 @@ -package View.Panels; - -import View.PlotDialog; -import com.sun.istack.internal.Nullable; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -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; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 02.06.2017. - */ -public class LMSPanel extends JPanel { - - - private JLabel[] labels; - private JTextField[] input; - private JButton startButton; - private JPanel continer; - private JPanel northPanel; - private JPanel centerPanel; - private PlotDialog plotDialog; - private GridBagConstraints gbc; - - public LMSPanel() { - this.labels = new JLabel[2]; - this.input = new JTextField[2]; - this.setLayout(new BorderLayout()); - this.northPanel = new JPanel(new BorderLayout()); - this.centerPanel = new JPanel(new BorderLayout()); - this.northPanel.setBorder(new TitledBorder("Konfiguration")); - this.centerPanel.setBorder(new TitledBorder("Visualisierung")); - - this.continer = new JPanel(); - this.continer.setLayout(new GridBagLayout()); - - this.gbc = new GridBagConstraints(); - this.gbc.anchor = GridBagConstraints.NORTH; - this.gbc.fill = GridBagConstraints.HORIZONTAL; - - addTextfieldAndInput(0, "Konstante", 0.5); - addTextfieldAndInput(1, "Fehler", 0.05); - - this.startButton = new JButton("Start"); - this.startButton.setFont(new Font("Verdana",Font.PLAIN, 16)); - addButton(2, startButton); - - this.northPanel.add(continer, BorderLayout.CENTER); - this.add(northPanel, BorderLayout.NORTH); - this.add(centerPanel, BorderLayout.CENTER); - } - - - private void addTextfieldAndInput(int row, String name, Double value) { - this.labels[row] = new JLabel(name); - this.labels[row].setFont(new Font("SansSerif", Font.PLAIN, 12)); - this.input[row] = new JTextField(); - this.input[row].setText("" + value); - - gbc.insets = new Insets(0, 5, 0, 0); - gbc.gridx = 0; - gbc.gridy = row; - gbc.weightx = 0.05; - gbc.weighty = 0.05; - continer.add(this.labels[row], gbc); - - gbc.gridx = 1; - gbc.gridy = row; - gbc.weightx = 0.9; - gbc.weighty = 0.05; - gbc.insets = new Insets(0, 0, 0, 5); - continer.add(this.input[row], gbc); - } - - private void addButton(int row, JButton button) { - JPanel buttonPanel = new JPanel(); - buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); - - gbc.insets = new Insets(30, 0, 5, 0); - - gbc.gridx = 0; - gbc.gridy = row; - gbc.weightx = 0.05; - gbc.weighty = 0.05; - gbc.gridwidth = 1; - buttonPanel.add(button); - continer.add(buttonPanel, gbc); - } - - public JButton getStartButton() { - return startButton; - } - - @Nullable - public String[] getInput() { - String[] input = new String[3]; - input[0] = this.input[0].getText(); - input[1] = this.input[1].getText(); - - 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) { - this.input = input; - } - - public PlotDialog getPlotDialog() { - return plotDialog; - } - - public void setPlotDialog(PlotDialog plotDialog) { - this.plotDialog = plotDialog; - if (this.centerPanel.getComponents().length > 0) - this.centerPanel.remove(0); - - this.centerPanel.add(plotDialog, BorderLayout.CENTER); - this.plotDialog.setVisible(true); - 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/MenuPanel.java b/src/main/java/View/Panels/MenuPanel.java deleted file mode 100644 index ff85cd8..0000000 --- a/src/main/java/View/Panels/MenuPanel.java +++ /dev/null @@ -1,52 +0,0 @@ -package View.Panels; - -import View.MainFrame; - -import javax.swing.*; -import java.awt.*; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 29.05.2017. - */ -public class MenuPanel extends JPanel { - - private MainFrame view; - private JMenuBar menuBar; - - private JMenu fileMenu; - private JMenu toolsMenu; - - private JMenuItem item; - private JMenuItem evaluate; - - public MenuPanel(MainFrame view) { - this.view = view; - this.setLayout(new BorderLayout()); - this.menuBar = new JMenuBar(); - this.fileMenu = new JMenu("Datei"); - this.toolsMenu = new JMenu("Extras"); - - - this.item = new JMenuItem("Exit"); - this.item.addActionListener(e -> { - System.exit(0); - }); - - this.evaluate = new JMenuItem("Evaluation"); - this.evaluate.addActionListener(e -> { - view.showEvauluationDialog(); - }); - - fileMenu.add(item); - toolsMenu.add(evaluate); - - menuBar.add(fileMenu); - menuBar.add(toolsMenu); - this.add(menuBar, BorderLayout.WEST); - this.add(new JSeparator(SwingConstants.HORIZONTAL), BorderLayout.SOUTH); - } -} diff --git a/src/main/java/View/Panels/OutputPanel.java b/src/main/java/View/Panels/OutputPanel.java deleted file mode 100644 index 9096aaf..0000000 --- a/src/main/java/View/Panels/OutputPanel.java +++ /dev/null @@ -1,93 +0,0 @@ -package View.Panels; - -import java.awt.BorderLayout; -import java.util.List; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextPane; -import javax.swing.border.TitledBorder; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 02.06.2017. - */ -public class OutputPanel extends JPanel { - - private JTextPane output; - private JScrollPane scrollPane; - private StringBuilder content; - - public OutputPanel() { - this.setBorder(new TitledBorder("Ausgabekanal")); - this.setLayout(new BorderLayout()); - output = new JTextPane(); - output.setEditable(false); - output.setContentType("text/html"); - - content = new StringBuilder(); - - scrollPane = new JScrollPane(output); - scrollPane.setWheelScrollingEnabled(true); - this.add(scrollPane, BorderLayout.CENTER); - - } - - - public void appendParagraph(String p) { - - content.append("

" + p + "

"); - - output.setText(content.toString()); - } - - public void appendParagraphWithHeading(String h1) { - - content.append("

" + h1 + "

"); - - output.setText(content.toString()); - } - - public void appendParagraphRed(String p) { - - content.append("

" + p + "

"); - - output.setText(content.toString()); - } - - public void appendParagraphGreen(String p) { - - content.append("

" + p + "

"); - - output.setText(content.toString()); - } - - public void logTable(List heading, List> rows) { - content.append("
"); - content.append(""); - content.append(""); - if (heading.size()>1){ - for (String str : heading) { - content.append(""); - } - } else { - content.append(""); - } - - content.append(""); - for (List row : rows) { - content.append(""); - for (String entry : row) { - content.append(""); - } - content.append(""); - } - content.append("
" + str + "" + heading.get(0) + "
" + entry + "
"); - content.append("
"); - output.setText(content.toString()); - } - - -} diff --git a/src/main/java/View/Panels/RMPanel.java b/src/main/java/View/Panels/RMPanel.java deleted file mode 100644 index ddad8b8..0000000 --- a/src/main/java/View/Panels/RMPanel.java +++ /dev/null @@ -1,141 +0,0 @@ -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; -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; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 21.06.2017. - */ -public class RMPanel extends JPanel { - - private JLabel labels; - private JTextField input; - private JButton startButton; - private JPanel continer; - private JPanel northPanel; - private JPanel centerPanel; - private PlotDialog plotDialog; - private GridBagConstraints gbc; - - public RMPanel() { - this.labels = new JLabel(); - - this.input = new JTextField(); - this.setLayout(new BorderLayout()); - this.northPanel = new JPanel(new BorderLayout()); - this.centerPanel = new JPanel(new BorderLayout()); - this.northPanel.setBorder(new TitledBorder("Konfiguration")); - this.centerPanel.setBorder(new TitledBorder("Visualisierung")); - - this.continer = new JPanel(); - this.continer.setLayout(new GridBagLayout()); - - this.gbc = new GridBagConstraints(); - this.gbc.anchor = GridBagConstraints.NORTH; - this.gbc.fill = GridBagConstraints.HORIZONTAL; - - addTextfieldAndInput(0, "\u00df (0 < \u00df < 1)", 0.5); - - - JPanel buttonPanel = new JPanel(); - buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); - this.startButton = new JButton("Start"); - this.startButton.setFont(new Font("Verdana",Font.PLAIN, 16)); - gbc.insets = new Insets(30, 0, 10, 0); - gbc.gridx = 0; - gbc.gridy = 2; - gbc.weightx = 0.05; - gbc.weighty = 0.05; - buttonPanel.add(startButton); - continer.add(buttonPanel, gbc); - - this.northPanel.add(continer, BorderLayout.CENTER); - this.add(northPanel, BorderLayout.NORTH); - this.add(centerPanel, BorderLayout.CENTER); - } - - - private void addTextfieldAndInput(int row, String name, Double value) { - this.labels = new JLabel(name); - this.labels.setFont(new Font("SansSerif", Font.PLAIN, 13)); - this.input = new JTextField(); - this.input.setText("" + value); - - gbc.insets = new Insets(0, 5, 0, 0); - gbc.gridx = 0; - gbc.gridy = row; - gbc.weightx = 0.05; - gbc.weighty = 0.05; - continer.add(this.labels, gbc); - - gbc.gridx = 1; - gbc.gridy = row; - gbc.weightx = 0.9; - gbc.weighty = 0.05; - gbc.insets = new Insets(0, 0, 0, 5); - continer.add(this.input, gbc); - } - - - public JButton getStartButton() { - return startButton; - } - - @Nullable - public String getInput() { - String input = ""; - input = this.input.getText(); - 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) { - this.input = input; - } - - public PlotDialog getPlotDialog() { - return plotDialog; - } - - public void setPlotDialog(PlotDialog plotDialog) { - this.plotDialog = plotDialog; - if (this.centerPanel.getComponents().length > 0) - this.centerPanel.remove(0); - - this.centerPanel.add(plotDialog, BorderLayout.CENTER); - this.plotDialog.setVisible(true); - 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/TSPanel.java b/src/main/java/View/Panels/TSPanel.java deleted file mode 100644 index e7bb8c0..0000000 --- a/src/main/java/View/Panels/TSPanel.java +++ /dev/null @@ -1,130 +0,0 @@ -package View.Panels; - -import View.PlotDialog; -import com.sun.istack.internal.Nullable; - -import javax.swing.*; -import javax.swing.border.TitledBorder; -import java.awt.*; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 26.06.2017. - */ -public class TSPanel extends JPanel{ - - private JLabel labels; - private JTextField input; - private JButton startButton; - private JPanel continer; - private JPanel northPanel; - private JPanel centerPanel; - private PlotDialog plotDialog; - private GridBagConstraints gbc; - - public TSPanel() { - this.labels = new JLabel(); - - this.input = new JTextField(); - this.setLayout(new BorderLayout()); - this.northPanel = new JPanel(new BorderLayout()); - this.centerPanel = new JPanel(new BorderLayout()); - this.northPanel.setBorder(new TitledBorder("Konfiguration")); - this.centerPanel.setBorder(new TitledBorder("Visualisierung")); - - this.continer = new JPanel(); - this.continer.setLayout(new GridBagLayout()); - - this.gbc = new GridBagConstraints(); - this.gbc.anchor = GridBagConstraints.NORTH; - this.gbc.fill = GridBagConstraints.HORIZONTAL; - - //addTextfieldAndInput(0, "\u00df (0 < \u00df < 1)", 0.5); - - JPanel buttonPanel = new JPanel(); - buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); - this.startButton = new JButton("Start"); - this.startButton.setFont(new Font("Verdana",Font.PLAIN, 16)); - gbc.insets = new Insets(10, 0, 10, 0); - gbc.gridx = 0; - gbc.gridy = 0; - gbc.weightx = 0.05; - gbc.weighty = 0.05; - buttonPanel.add(startButton); - continer.add(buttonPanel, gbc); - - this.northPanel.add(continer, BorderLayout.CENTER); - this.add(northPanel, BorderLayout.NORTH); - this.add(centerPanel, BorderLayout.CENTER); - } - - - private void addTextfieldAndInput(int row, String name, Double value) { - this.labels = new JLabel(name); - this.labels.setFont(new Font("SansSerif", Font.PLAIN, 13)); - this.input = new JTextField(); - this.input.setText("" + value); - - gbc.insets = new Insets(0, 5, 0, 0); - gbc.gridx = 0; - gbc.gridy = row; - gbc.weightx = 0.05; - gbc.weighty = 0.05; - continer.add(this.labels, gbc); - - gbc.gridx = 0; - gbc.gridy = row; - gbc.weightx = 0.9; - gbc.weighty = 0.05; - gbc.insets = new Insets(0, 0, 0, 5); - continer.add(this.input, gbc); - } - - - public JButton getStartButton() { - return startButton; - } - - @Nullable - public String getInput() { - String input = ""; - input = this.input.getText(); - 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) { - this.input = input; - } - - public PlotDialog getPlotDialog() { - return plotDialog; - } - - public void setPlotDialog(PlotDialog plotDialog) { - this.plotDialog = plotDialog; - if (this.centerPanel.getComponents().length > 0) - this.centerPanel.remove(0); - - this.centerPanel.add(plotDialog, BorderLayout.CENTER); - this.plotDialog.setVisible(true); - 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/PlotDialog.java b/src/main/java/View/PlotDialog.java deleted file mode 100644 index 67c0cc9..0000000 --- a/src/main/java/View/PlotDialog.java +++ /dev/null @@ -1,144 +0,0 @@ -package View; - -import Model.Line; -import org.jfree.chart.ChartFactory; -import org.jfree.chart.ChartPanel; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.plot.PlotOrientation; -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.util.ShapeUtilities; - -import javax.swing.*; -import java.awt.*; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedList; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 29.05.2017. - */ -public class PlotDialog extends JPanel { - - private JFreeChart chart; - private ChartPanel panel; - private XYSeriesCollection datapoints; - private XYSeries series; - private Double min; - private Double max; - private XYPlot xyPlot; - private int seriesCount; - - private XYLineAndShapeRenderer renderer; - private Shape diamond; - - public PlotDialog() { - super(); -// this.setPreferredSize(new Dimension(1000, 1000)); -// this.setMinimumSize(new Dimension(1000, 800)); - this.setLayout(new BorderLayout()); - seriesCount = 1; - } - - public void createPlot(LinkedList points) { - if (!points.isEmpty()) { - try { - Thread thread = new Thread(() -> convertData(points)); - thread.start(); - thread.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - //createScatterPlot - chart = ChartFactory.createXYLineChart("", - "X", "Y", datapoints, PlotOrientation.VERTICAL, true, true, false); - diamond = ShapeUtilities.createDiamond(2f); - chart.setBorderVisible(false); - chart.setAntiAlias(true); - chart.getPlot().setBackgroundPaint(Color.WHITE); - chart.setBorderVisible(false); - - - xyPlot = (XYPlot) chart.getPlot(); - xyPlot.setDomainCrosshairVisible(true); - xyPlot.setRangeCrosshairVisible(true); - - - renderer = (XYLineAndShapeRenderer) xyPlot.getRenderer(); - renderer.setSeriesLinesVisible(0, false); - renderer.setSeriesShapesVisible(0, true); - renderer.setSeriesLinesVisible(1, true); - renderer.setSeriesLinesVisible(1, true); - renderer.setSeriesPaint(0, Color.blue); - renderer.setSeriesShape(0, diamond); - renderer.setBaseSeriesVisible(true); - - - xyPlot.setDomainCrosshairVisible(true); - xyPlot.setRangeCrosshairVisible(true); - - panel = new ChartPanel(chart); - panel.setMouseZoomable(false); - this.add(panel, BorderLayout.CENTER); - } - - public void clear(){ - if (datapoints != null) - datapoints.removeAllSeries(); - } - - public void addLineToPlot(double m, double b, Paint color, String name) { - - XYSeries linesA = new XYSeries(name); - linesA.add(min.doubleValue(), min * m + b); - linesA.add(max.doubleValue(), max * m + b); - - datapoints.addSeries(linesA); - - renderer.setSeriesPaint(seriesCount, color); - renderer.setSeriesStroke(seriesCount, new BasicStroke(2.0f)); - renderer.setBaseSeriesVisible(true); - renderer.setSeriesLinesVisible(seriesCount, true); - seriesCount++; - - } - - - public void addLineToPlot(double m, double b, String name) { - - XYSeries linesA = new XYSeries(name); - linesA.add(min.intValue(), min.intValue() * m + b); - linesA.add(max.intValue(), max.intValue() * m + b); - - datapoints.addSeries(linesA); - seriesCount = xyPlot.getSeriesCount(); - renderer.setSeriesPaint(seriesCount, Color.red); - renderer.setSeriesStroke(seriesCount, new BasicStroke(2.0f)); - renderer.setBaseSeriesVisible(true); - renderer.setSeriesLinesVisible(seriesCount, true); - } - - private void convertData(LinkedList points) { - datapoints = new XYSeriesCollection(); - ArrayList coordinates = new ArrayList<>(); - series = new XYSeries("points"); - for (Line p : points) { - series.add(p.getM().doubleValue(), p.getB().doubleValue() * (-1)); - coordinates.add(p.getM()); - - } - this.max = series.getMaxX(); - this.min = series.getMinX(); - datapoints.addSeries(series); - } - - -} - diff --git a/src/main/java/View/custom/ButtonGroupAtLeastOne.java b/src/main/java/View/custom/ButtonGroupAtLeastOne.java deleted file mode 100644 index 2622ec0..0000000 --- a/src/main/java/View/custom/ButtonGroupAtLeastOne.java +++ /dev/null @@ -1,78 +0,0 @@ -package View.custom; - -import java.util.HashSet; -import java.util.Set; -import javax.swing.AbstractButton; -import javax.swing.ButtonGroup; -import javax.swing.ButtonModel; - -/** - * Source: https://stackoverflow.com/questions/14892515/how-to-enforce-at-least-one-checkbox-in-a-group-is-selected - * - * A ButtonGroup for check-boxes enforcing that at least two remains selected. - * - * When the group has exactly two buttons, deselecting the last selected one - * automatically selects the other. - * - * When the group has more buttons, deselection of the last selected one is denied. - */ -public class ButtonGroupAtLeastOne extends ButtonGroup { - - private final Set selected = new HashSet<>(); - - @Override - public void setSelected(ButtonModel model, boolean b) { - if (b && !this.selected.contains(model) ) { - select(model, true); - } else if (!b && this.selected.contains(model)) { - if (this.buttons.size() == 3 && this.selected.size() == 2) { - select(model, false); - - AbstractButton otherOne = this.buttons.get(0).getModel() == model ? - this.buttons.get(1) : this.buttons.get(0); - - AbstractButton otherTwo = this.buttons.get(1).getModel() == model ? - this.buttons.get(2) : this.buttons.get(1); - - AbstractButton otherThree = this.buttons.get(2).getModel() == model ? - this.buttons.get(1) : this.buttons.get(2); - - - select(otherOne.getModel(), true); - select(otherTwo.getModel(), true); - select(otherThree.getModel(), true); - } else if (this.selected.size() > 2) { - this.selected.remove(model); - model.setSelected(false); - } - } - } - - private void select(ButtonModel model, boolean b) { - if (b) { - this.selected.add(model); - } else { - this.selected.remove(model); - } - model.setSelected(b); - } - - @Override - public boolean isSelected(ButtonModel m) { - return this.selected.contains(m); - } - - public void addAll(AbstractButton... buttons) { - for (AbstractButton button : buttons) { - add(button); - } - } - - @Override - public void add(AbstractButton button) { - if (button.isSelected()) { - this.selected.add(button.getModel()); - } - super.add(button); - } -} \ No newline at end of file diff --git a/src/main/java/View/custom/ColorColumnRenderer.java b/src/main/java/View/custom/ColorColumnRenderer.java deleted file mode 100644 index 6d2605f..0000000 --- a/src/main/java/View/custom/ColorColumnRenderer.java +++ /dev/null @@ -1,38 +0,0 @@ -package View.custom; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Font; -import javax.swing.JLabel; -import javax.swing.JTable; -import javax.swing.table.DefaultTableCellRenderer; - -/** - * Source: http://esus.com/creating-a-jtable-with-a-different-background-color-per-column/ - * - * Applied background and foreground color to single column of a JTable - * in order to distinguish it apart from other columns. - */ -public class ColorColumnRenderer extends DefaultTableCellRenderer { - - Color bkgndColor, fgndColor; - - public ColorColumnRenderer(Color bkgnd, Color foregnd) { - super(); - bkgndColor = bkgnd; - fgndColor = foregnd; - } - - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, - boolean hasFocus, int row, int column) { - Component cell = super.getTableCellRendererComponent - (table, value, isSelected, hasFocus, row, column); - - cell.setBackground(bkgndColor); - cell.setForeground(fgndColor); - cell.setFont(new Font("SansSerif", Font.BOLD, 12)); - this.setHorizontalAlignment(JLabel.CENTER); - - return cell; - } -} \ No newline at end of file diff --git a/src/main/java/model/DCEL/DoublyConnectedEdgeList.java b/src/main/java/model/DCEL/DoublyConnectedEdgeList.java new file mode 100644 index 0000000..5c09e02 --- /dev/null +++ b/src/main/java/model/DCEL/DoublyConnectedEdgeList.java @@ -0,0 +1,154 @@ +package model.DCEL; + + +import model.Point; + +import java.util.LinkedList; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 30.05.2017. + */ +public class DoublyConnectedEdgeList { + + private LinkedList nodes; + private LinkedList edges; + private LinkedList faces; + + public DoublyConnectedEdgeList() { + this.nodes = new LinkedList<>(); + this.edges = new LinkedList<>(); + this.faces = new LinkedList<>(); + } + + public Node createNode(Point point, String id) { + + Node node = new Node(); + node.setPoint(point); + node.setID(id); + + return node; + } + + public Edge createEdge(Node source, Node destination, String id) { + + Edge edge = new Edge(); + Edge twin = new Edge(); + + edge.setOrigin(source); + edge.setID(id); + edge.setTwin(twin); + twin.setOrigin(destination); + twin.setID("#" + id); + twin.setTwin(edge); + + source.setIncidentEdge(edge); + destination.setIncidentEdge(twin); + + return edge; + } + + public Face createFace(Edge outerComponent, Edge innerComponent, String id) { + + Face face = new Face(outerComponent, null); + face.setID(id); + Edge tempEdge; + + if (outerComponent != null) { + tempEdge = outerComponent; + do { + tempEdge.setIncidentFace(face); + tempEdge = tempEdge.getNext(); + } while (!tempEdge.equals(outerComponent)); + } + + if (innerComponent != null) { + LinkedList componentlist; + componentlist = face.getInnerComponents(); + componentlist.add(innerComponent); + tempEdge = innerComponent; + do { + tempEdge.setIncidentFace(face); + tempEdge = tempEdge.getNext(); + } while (!tempEdge.equals(innerComponent)); + } + + return face; + } + + public void createConnection(Edge edge, Edge succ) { + edge.setNext(succ); + succ.setPrev(edge); + + edge.getTwin().setPrev(succ.getTwin()); + succ.getTwin().setNext(edge.getTwin()); + } + + public LinkedList getEdgesOfInnerComponents(Face face) { + + LinkedList list = new LinkedList(); + LinkedList innerComponents = face.getInnerComponents(); + Edge it; + for (Edge e : innerComponents) { + it = e; + do { + list.add(it); + //System.out.println("Current Edge: "+it.getID()+"\tNext Edge: "+it.getNext().getID()); + it = it.getNext(); + } while (it != e); + } + + return list; + } + + public LinkedList getEdgesOfOuterComponents(Face face) { + + LinkedList list = new LinkedList(); + Edge it = face.getOuterComponent(); + do { + list.add(it); + //System.out.println("Current Edge: "+it.getID()+"\tNext Edge: "+it.getNext().getID()); + it = it.getNext(); + } while (it != face.getOuterComponent()); + + return list; + } + + + public LinkedList getConnectedEdges(Node node) { + Edge edge = node.getIncidentEdge(); + LinkedList list = new LinkedList(); + do { + list.add(edge); + edge = edge.getNext(); + } while (node != edge.getOrigin()); + return list; + } + + public LinkedList getNodes() { + return nodes; + } + + public void setNodes(LinkedList nodes) { + this.nodes = nodes; + } + + public LinkedList getEdges() { + return edges; + } + + public void setEdges(LinkedList edges) { + this.edges = edges; + } + + public LinkedList getFaces() { + return faces; + } + + public void setFaces(LinkedList faces) { + this.faces = faces; + } +} diff --git a/src/main/java/model/DCEL/Edge.java b/src/main/java/model/DCEL/Edge.java new file mode 100644 index 0000000..8955fdc --- /dev/null +++ b/src/main/java/model/DCEL/Edge.java @@ -0,0 +1,117 @@ +package model.DCEL; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 30.05.2017. + */ +public class Edge { + + private Node origin; + private Edge twin; + private Face incidentFace; + private Edge next; + private Edge prev; + private String id; + + public Edge() { + new Edge(null, null, null, null, null); + } + + public Edge(Node origin, Edge twin, Edge next, Edge prev, Face incidentFace) { + this.origin = origin; + this.twin = twin; + this.next = next; + this.prev = prev; + this.incidentFace = incidentFace; + } + + public Node getOrigin() { + return origin; + } + + public void setOrigin(Node origin) { + this.origin = origin; + } + + public Edge getTwin() { + return twin; + } + + public void setTwin(Edge twin) { + this.twin = twin; + } + + public Face getIncidentFace() { + return incidentFace; + } + + public void setIncidentFace(Face incidentFace) { + this.incidentFace = incidentFace; + } + + public Edge getNext() { + return next; + } + + public void setNext(Edge next) { + this.next = next; + } + + public Edge getPrev() { + return prev; + } + + public void setPrev(Edge prev) { + this.prev = prev; + } + + public boolean hasNext() { + if (getNext() == null) { + return false; + } else { + return true; + } + + } + + public Edge insertNode(Node node) { + + Edge edge = new Edge(); + Edge twin = new Edge(); + + edge.setOrigin(node); + edge.setNext(this.getNext()); + edge.setPrev(this); + edge.setTwin(twin); + edge.setIncidentFace(this.getIncidentFace()); + + twin.setOrigin(this.getTwin().getOrigin()); + twin.setPrev(this.getTwin().getPrev()); + twin.setNext(this.getTwin()); + twin.setTwin(edge); + twin.setIncidentFace(this.getTwin().getIncidentFace()); + + Node twinOrigin = this.getTwin().getOrigin(); + twinOrigin.setIncidentEdge(twin); + node.setIncidentEdge(edge); + + this.getTwin().setOrigin(node); + this.getTwin().getPrev().setNext(twin); + this.getNext().setPrev(edge); + this.setNext(edge); + this.getTwin().setPrev(twin); + + return edge; + } + + public String getID() { + return this.id; + } + + public void setID(String id) { + this.id = id; + } +} diff --git a/src/main/java/model/DCEL/Face.java b/src/main/java/model/DCEL/Face.java new file mode 100644 index 0000000..5d94334 --- /dev/null +++ b/src/main/java/model/DCEL/Face.java @@ -0,0 +1,125 @@ +package model.DCEL; + +import java.util.LinkedList; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 30.05.2017. + */ +public class Face { + + private LinkedList innerComponents; + private Edge outerComponent; + private String id; + + public Face() { + this.outerComponent = null; + this.innerComponents = new LinkedList<>(); + } + + public Face(Edge outerComponent, LinkedList innerComponents) { + this.outerComponent = outerComponent; + if (innerComponents != null) { + this.innerComponents = innerComponents; + } else { + this.innerComponents = new LinkedList<>(); + + } + + } + + public LinkedList getInnerComponents() { + return innerComponents; + } + + public void setInnerComponents(LinkedList innerComponents) { + this.innerComponents = innerComponents; + } + + public Edge getOuterComponent() { + return outerComponent; + } + + public void setOuterComponent(Edge outerComponent) { + this.outerComponent = outerComponent; + } + + public Face insertEdge(Edge edgeWithSameDestination, Edge edgeToMySource) { + + if (edgeWithSameDestination.getIncidentFace().equals(this) || edgeToMySource.getIncidentFace() + .equals(this)) { + LinkedList components = new LinkedList(); + for (Edge e : innerComponents) { + components.add(e); + } + Face face = new Face(getOuterComponent(), components); + Edge edge = new Edge(); + Edge twin = new Edge(); + + edge.setOrigin(edgeWithSameDestination.getOrigin()); + edge.setTwin(twin); + edge.setNext(edgeToMySource); + edge.setPrev(edgeWithSameDestination.getPrev()); + + twin.setOrigin(edgeToMySource.getOrigin()); + twin.setTwin(edge); + twin.setNext(edgeWithSameDestination); + twin.setPrev(edgeToMySource.getPrev()); + + Edge tempEdge = edge.getNext(); + Edge tempTwin = twin.getNext(); + //kreis umlaufen um festzustellen welche fläche kleiner ist + while ((tempEdge.equals(edge) == false) && (tempTwin.equals(twin) == false)) { + tempEdge = tempEdge.getNext(); + tempTwin = tempTwin.getNext(); + } + + if (tempEdge.equals(edge)) { + setOuterComponent(twin); + twin.setIncidentFace(this); + face.setOuterComponent(edge); + } else { + setOuterComponent(edge); + edge.setIncidentFace(this); + face.setOuterComponent(twin); + } + + LinkedList bla = new LinkedList(); + Edge iterEdge = face.getOuterComponent(); + bla.add(face.getOuterComponent()); + + while (iterEdge.hasNext()) { + bla.add(iterEdge.getNext()); + iterEdge = iterEdge.getNext(); + } + + for (Edge e : face.getInnerComponents()) { + iterEdge = e; + while (iterEdge.hasNext()) { + bla.add(iterEdge.getNext()); + iterEdge = iterEdge.getNext(); + } + } + + for (Edge e : bla) { + e.setIncidentFace(face); + } + return face; + } else { + throw new IllegalArgumentException( + "Die angegebenen Kanten haben keinen zusammenhang mit der Fläche!"); + } + + } + + public String getID() { + return this.id; + } + + public void setID(String id) { + this.id = id; + } +} diff --git a/src/main/java/model/DCEL/Node.java b/src/main/java/model/DCEL/Node.java new file mode 100644 index 0000000..985b830 --- /dev/null +++ b/src/main/java/model/DCEL/Node.java @@ -0,0 +1,50 @@ +package model.DCEL; + +import model.Point; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 30.05.2017. + */ +public class Node { + + private Point point; + private Edge incidentEdge; + private String id; + + public Node() { + new Node(null, null); + } + + public Node(Point point, Edge incidentEdge) { + this.point = point; + this.incidentEdge = incidentEdge; + } + + public Point getPoint() { + return point; + } + + public void setPoint(Point point) { + this.point = point; + } + + public Edge getIncidentEdge() { + return incidentEdge; + } + + public void setIncidentEdge(Edge incidentEdge) { + this.incidentEdge = incidentEdge; + } + + public String getID() { + return this.id; + } + + public void setID(String id) { + this.id = id; + } +} diff --git a/src/main/java/model/Interval.java b/src/main/java/model/Interval.java new file mode 100644 index 0000000..8da7c66 --- /dev/null +++ b/src/main/java/model/Interval.java @@ -0,0 +1,51 @@ +package model; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 16.06.2017. + */ +public class Interval { + + private double upper; + private double lower; + private Boolean activity; + + public Interval(double lower, double upper) { + this.upper = upper; + this.lower = lower; + this.activity = true; + } + + public Boolean getActivity() { + return activity; + } + + public void setActivity(Boolean isActive) { + this.activity = isActive; + } + + public double getUpper() { + return upper; + } + + public void setUpper(double upper) { + this.upper = upper; + } + + public double getLower() { + return lower; + } + + public void setLower(double lower) { + this.lower = lower; + } + + public Double getDistance() { + + return Math.abs(this.upper - this.lower); + } + +} \ No newline at end of file diff --git a/src/main/java/model/Line.java b/src/main/java/model/Line.java new file mode 100644 index 0000000..0532286 --- /dev/null +++ b/src/main/java/model/Line.java @@ -0,0 +1,107 @@ +package model; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 12.06.2017. + */ +public class Line { + + private final Double MAX = 9999d; + private final Double MIN = -9999d; + + + private Double m; + private Double b; + + private Double x1; + private Double x2; + private Double y1; + private Double y2; + + private String id; + + public Line(double m, double b, String id) { + this.m = m; + this.b = b; + + this.x1 = MIN; + this.y1 = (MIN * m) + b; + this.x2 = MAX * 0.5; + this.y2 = ((MAX * 0.5) * m) + b; + this.id = id; + } + + + public Line(double m, double b) { + this.m = m; + this.b = b; + + this.x1 = MIN; + this.y1 = (MIN * m) + b; + this.x2 = MAX * 0.5; + this.y2 = ((MAX * 0.5) * m) + b; + } + + public Line(double x1, double x2, double y1, double y2) { + this.x1 = x1; + this.x2 = x2; + this.y1 = y1; + this.y2 = y2; + + this.m = (y2 - y1) / (x2 - x1); + this.b = y2 - (x2 * m); + + } + + public Double getM() { + return m; + } + + public void setM(double m) { + this.m = m; + } + + public Double getB() { + return b; + } + + public void setB(double b) { + this.b = b; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Double getX1() { + return x1; + } + + public Double getX2() { + return x2; + } + + public Double getY1() { + return y1; + } + + public Double getY2() { + return y2; + } + + public void setEndPoints(double x1, double y1, double x2, double y2) { + this.x1 = x1; + this.x2 = x2; + this.y1 = y1; + this.y2 = y2; + } + + +} diff --git a/src/main/java/model/LineModel.java b/src/main/java/model/LineModel.java new file mode 100644 index 0000000..5244712 --- /dev/null +++ b/src/main/java/model/LineModel.java @@ -0,0 +1,98 @@ +package model; + +import java.util.Collections; +import java.util.LinkedList; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 28.05.2017. + */ +public class LineModel { + + private LinkedList nodes; + private LinkedList lines; + private Double xMinimum; + private Double xMaximum; + private Double yMinimum; + private Double yMaximum; + + public LineModel() { + nodes = new LinkedList<>(); + lines = new LinkedList<>(); + } + + public void setXbounds() { + LinkedList xlist = new LinkedList<>(); + for (Point p : nodes) { + xlist.add(p.getX()); + } + + xMaximum = Collections.max(xlist); + xMinimum = Collections.min(xlist); + } + + public void setYbounds() { + LinkedList ylist = new LinkedList<>(); + for (Point p : nodes) { + ylist.add(p.getY()); + } + + yMaximum = Collections.max(ylist); + yMinimum = Collections.min(ylist); + } + + public void addNode(Point node) { + this.nodes.add(node); + } + + public void addLine(Line line) { + this.lines.add(line); + } + + public LinkedList getNodes() { + return nodes; + } + + public LinkedList getLines() { + return lines; + } + + public void setLines(LinkedList lines) { + 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/model/Pair.java b/src/main/java/model/Pair.java new file mode 100644 index 0000000..d870165 --- /dev/null +++ b/src/main/java/model/Pair.java @@ -0,0 +1,35 @@ +package model; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 19.06.2017. + */ +public class Pair { + + private Integer p1; + private Integer p2; + + public Pair(Integer p1, Integer p2) { + this.p1 = p1; + this.p2 = p2; + } + + public Integer getP1() { + return p1; + } + + public void setP1(Integer p1) { + this.p1 = p1; + } + + public Integer getP2() { + return p2; + } + + public void setP2(Integer p2) { + this.p2 = p2; + } +} diff --git a/src/main/java/model/Point.java b/src/main/java/model/Point.java new file mode 100644 index 0000000..850476e --- /dev/null +++ b/src/main/java/model/Point.java @@ -0,0 +1,65 @@ +package model; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 28.05.2017. + */ +public class Point implements Comparable { + + private Double x; + private Double y; + private String id; + + public Point(Double x, Double y) { + this.x = x; + this.y = y; + } + + public Point(Double x, Double y, String id) { + this.x = x; + this.y = y; + this.id = id; + } + + public Double getX() { + return x; + } + + public void setX(Double x) { + this.x = x; + } + + public Double getY() { + return y; + } + + public void setY(Double y) { + this.y = y; + } + + @Override + public int compareTo(Point o) { + if (this.getX() == o.getX()) { + if (this.getY() <= o.getY()) { + return -1; + } else { + return 1; + } + } else if (this.getX() < o.getX()) { + return -1; + } else { + return 1; + } + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } +} diff --git a/src/main/java/presenter/AbstractPresenter.java b/src/main/java/presenter/AbstractPresenter.java new file mode 100644 index 0000000..6de3500 --- /dev/null +++ b/src/main/java/presenter/AbstractPresenter.java @@ -0,0 +1,210 @@ +package presenter; + +import model.Interval; +import model.Line; +import model.LineModel; +import presenter.algorithms.IntersectionCounter; +import presenter.evaluation.EvaluateAlgorithms; +import view.MainFrame; + +import javax.swing.*; +import java.util.LinkedList; +import java.util.List; +import java.util.Observable; +import java.util.Observer; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 10.09.2017. + */ +public abstract class AbstractPresenter implements Observer { + + private LineModel model; + private MainFrame view; + + private EvaluateAlgorithms eval; + + + public AbstractPresenter(LineModel model, MainFrame view) { + this.model = model; + this.view = view; + } + + @Override + public void update(Observable o, Object arg) { + String[] result = ((String[]) arg); + + if (result[0] == "eval-dataset-generated") { + SwingUtilities.invokeLater(() -> getView().addEvalDataset(getEval().getData())); + } + + if (result[0] == "eval-d") { + SwingUtilities.invokeLater(() -> getView().appendEvalResult(result, Integer.parseInt(result[1]), false)); + } + + if (result[0] == "eval-ds") { + SwingUtilities.invokeLater(() -> getView().appendEvalResult(result)); + } + + if (result[0] == "eval-t") { + SwingUtilities.invokeLater(() -> getView().appendEvalResult(result, Integer.parseInt(result[1]), true)); + } + + if (result[0] == "lines-res") { + SwingUtilities.invokeLater(() -> getView().drawLineResult(result, Integer.parseInt(result[1]))); + } + + if (result[0] == "lines-res-mult") { + SwingUtilities.invokeLater(() -> getView().drawLineResults(result)); + } + + if (result[0] == "lms") { + SwingUtilities.invokeLater(() -> { + getView().visualizeLMS(Double.parseDouble(result[1]), Double.parseDouble(result[2])); + //getView().setLmsIsComplete(true); + getView().logHeading("Least Median of Squares"); + getView().log("m: " + result[1]); + getView().log("b: " + result[2]); + getView().logSuccess("Berechnung wurde Erfolgreich durchgeführt
"); + }); + } + + if (result[0] == "rm") { + SwingUtilities.invokeLater(() -> { + getView().visualizeRM(Double.parseDouble(result[1]), Double.parseDouble(result[2])); + getView().logHeading("Repeated Median Estimator"); + getView().log("m: " + result[1]); + getView().log("b: " + result[2]); + getView().logSuccess("Berechnung wurde Erfolgreich durchgeführt
"); + }); + } + + if (result[0] == "ts") { + SwingUtilities.invokeLater(() -> { + getView().visualizeTS(Double.parseDouble(result[1]), Double.parseDouble(result[2])); + getView().logHeading("Theil-Sen Estimator"); + getView().log("m: " + result[1]); + getView().log("b: " + result[2]); + getView().logSuccess("Berechnung wurde Erfolgreich durchgeführt
"); + }); + } + + if (result[0] == "import") { + Double max = Double.parseDouble(result[1]); + Double current = Double.parseDouble(result[2]); + Integer progress = (int) (100 * (current / max)); + //100% erreicht + if (progress == 100) { + SwingUtilities.invokeLater(() -> { + getView().showImportProgress(progress); + getView().enableFunctionality(); + getView().getProgressDialog().dispose(); + }); + setup(); + Thread t = new Thread(() -> { + calculateIntersections(); + }); + t.start(); + try { + t.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } else { + SwingUtilities.invokeLater(() -> { + getView().showImportProgress(progress); + }); + } + } + if (result[0] == "export") { + SwingUtilities.invokeLater(() -> { + getView().logSuccess("Export Erfolgreich"); + getView().log(result[1] + "
"); + }); + } + + if (result[0] == "generator") { + SwingUtilities.invokeLater(() -> { + getView().logSuccess("Generierung Erfolgreich"); + getView().log(result[1] + "
"); + setup(); + }); + } + } + + public void setup() { + //Darstellung der Schnittpunkte in einer Tabelle + List heading = new LinkedList<>(); + List> rows = new LinkedList<>(); + heading.add("Geraden im Dualraum"); + for (int j = 0; j < getModel().getLines().size() - 2; j++) { + LinkedList rowEntry = new LinkedList<>(); + Line p1 = getModel().getLines().get(j); + String sign = p1.getB() < 0 ? "" : "+"; + rowEntry.add("f(x) = " +String.format("%.3f", p1.getM()) + "x "+ sign + String.format("%.3f",p1.getB())); + + if (j + 1 < getModel().getLines().size()) { + Line p2 = getModel().getLines().get(j + 1); + sign = p2.getB() < 0 ? "" : "+"; + rowEntry.add("f(x) = " +String.format("%.3f",p2.getM()) + "x" + sign + String.format("%.3f", p2.getB())); + } + + if (j + 2 < getModel().getLines().size()) { + Line p3 = getModel().getLines().get(j + 2); + sign = p3.getB() < 0 ? "" : "+"; + rowEntry.add("f(x) = " + String.format("%.3f",p3.getM()) + "x"+ sign + String.format("%.3f",p3.getB())); + } + rows.add(rowEntry); + } + getView().createTable(heading, rows); + + getView().log("
"); + } + + + + public void calculateIntersections() { + try { + Thread thread = new Thread(() -> { + IntersectionCounter counter = new IntersectionCounter(); + counter.run(getModel().getLines(), new Interval(-99999, 99999)); + counter.calculateIntersectionAbscissas(getModel()); + getModel().setXbounds(); + getModel().setYbounds(); + + }); + thread.start(); + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + + public LineModel getModel() { + return model; + } + + public void setModel(LineModel model) { + this.model = model; + } + + public MainFrame getView() { + return view; + } + + public void setView(MainFrame view) { + this.view = view; + } + + public EvaluateAlgorithms getEval() { + return eval; + } + + public void setEval(EvaluateAlgorithms eval) { + this.eval = eval; + } +} diff --git a/src/main/java/presenter/Presenter.java b/src/main/java/presenter/Presenter.java new file mode 100644 index 0000000..6ac4af5 --- /dev/null +++ b/src/main/java/presenter/Presenter.java @@ -0,0 +1,196 @@ +package presenter; + +import model.LineModel; +import presenter.algorithms.LeastMedianOfSquaresEstimator; +import presenter.algorithms.RepeatedMedianEstimator; +import presenter.algorithms.TheilSenEstimator; +import presenter.evaluation.EvaluateAlgorithms; +import presenter.generator.DatasetGenerator; +import presenter.io.DataExporter; +import presenter.io.DataImporter; +import presenter.io.EvalResultLatexExport; +import view.MainFrame; + +import javax.swing.table.DefaultTableModel; +import java.io.File; + + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 28.05.2017. + */ +public class Presenter extends AbstractPresenter{ + + /* Threads */ + private Thread tsThread; + private Thread rmThread; + private Thread lmsThread; + private Thread importThread; + private Thread exportThread; + private Thread exportResultThread; + private Thread generatorThread; + private Thread evalThread; + + public Presenter(LineModel model, MainFrame view) { + super(model, view); + } + + + public void visualizeDualLines() { + getView().createDualityDialog(); + } + + /*************************************************************************************************************************** + * Ausführung der Algorithmen + ***************************************************************************************************************************/ + public void calculateLMS(String[] input) { + if (input[0] != null && input[1] != null) { + if (lmsThread == null || !lmsThread.isAlive()) { + lmsThread = new Thread(() -> { + Double constant = Double.parseDouble(input[0]); + Double error = Double.parseDouble(input[1]); + LeastMedianOfSquaresEstimator lms = new LeastMedianOfSquaresEstimator(getModel().getLines(), getModel().getNodes(), this); + lms.setConstant(constant); + lms.setQuantileError(error); + lms.addObserver(this); + lms.run(); + lms.getResult(); + }); + lmsThread.start(); + try { + lmsThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + + public void calculateRM(String input) { + if (input != null) { + if (rmThread == null || !rmThread.isAlive()) { + rmThread = new Thread(() -> { + RepeatedMedianEstimator rm = new RepeatedMedianEstimator(getModel().getLines(), this); + Double parameter = Double.parseDouble(input); + rm.setBeta(parameter); + rm.addObserver(this); + rm.run(); + rm.getResult(); + }); + rmThread.start(); + try { + rmThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + + public void calculateTS(String input) { + if (input != null) { + if (tsThread == null || !tsThread.isAlive()) { + tsThread = new Thread(() -> { + TheilSenEstimator ts = new TheilSenEstimator(getModel().getLines(), getModel().getNodes(), this); + ts.addObserver(this); + ts.run(); + ts.getResult(); + }); + tsThread.start(); + try { + tsThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } + + /*************************************************************************************************************************** + * Hilfsmethoden + ***************************************************************************************************************************/ + + public void startImport(File file) { + if (importThread == null || !importThread.isAlive()) { + importThread = new Thread(() -> { + DataImporter importer = new DataImporter(file, this); + importer.addObserver(this); + importer.run(); + }); + importThread.start(); + try { + importThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + public void startExport(File file) { + if (exportThread == null || !exportThread.isAlive()) { + exportThread = new Thread(() -> { + DataExporter exporter = new DataExporter(getModel(), file); + exporter.addObserver(this); + exporter.export(); + }); + exportThread.start(); + try { + exportThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + public void startResultExport(DefaultTableModel model, File file) { + if (exportResultThread == null || !exportResultThread.isAlive()) { + exportResultThread = new Thread(() -> { + EvalResultLatexExport exporter = new EvalResultLatexExport(model, file); + exporter.writeFile(); + }); + exportResultThread.start(); + try { + exportResultThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + public void generateDataset() { + if (generatorThread == null || !generatorThread.isAlive()) { + generatorThread = new Thread(() -> { + DatasetGenerator generator = new DatasetGenerator(); + generator.addObserver(this); + getModel().setLines(generator.generateCircle(100)); + calculateIntersections(); + getView().enableFunctionality(); + }); + generatorThread.start(); + try { + generatorThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + public void startEvaluation(int typ, int n, int alg, String datasettyp) { + + if (evalThread == null || !evalThread.isAlive()) { + evalThread = new Thread(() -> { + try { + setEval(new EvaluateAlgorithms(typ, n, alg, datasettyp)); + getEval().addObserver(this); + getEval().run(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }); + evalThread.start(); + } + } +} diff --git a/src/main/java/Presenter/Algorithms/Algorithm.java b/src/main/java/presenter/algorithms/Algorithm.java similarity index 75% rename from src/main/java/Presenter/Algorithms/Algorithm.java rename to src/main/java/presenter/algorithms/Algorithm.java index 9a1cee3..6f12252 100644 --- a/src/main/java/Presenter/Algorithms/Algorithm.java +++ b/src/main/java/presenter/algorithms/Algorithm.java @@ -1,4 +1,4 @@ -package Presenter.Algorithms; +package presenter.algorithms; /** * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. @@ -9,6 +9,7 @@ package Presenter.Algorithms; */ public interface Algorithm { - void run(); - void getResult(); + void run(); + + void getResult(); } diff --git a/src/main/java/presenter/algorithms/BinomialCoeffizient.java b/src/main/java/presenter/algorithms/BinomialCoeffizient.java new file mode 100644 index 0000000..a1c54b4 --- /dev/null +++ b/src/main/java/presenter/algorithms/BinomialCoeffizient.java @@ -0,0 +1,25 @@ +package presenter.algorithms; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 26.06.2017. + */ +public class BinomialCoeffizient { + + public static Double run(int n, int k) { + int res = 1; + + if (k > n - k) + k = n - k; + + for (int i = 0; i < k; ++i) { + res *= (n - i); + res /= (i + 1); + } + + return Double.valueOf(res); + } +} diff --git a/src/main/java/Presenter/Algorithms/Comparators/YOrderLineComparatorBegin.java b/src/main/java/presenter/algorithms/Comparators/YOrderLineComparatorBegin.java similarity index 75% rename from src/main/java/Presenter/Algorithms/Comparators/YOrderLineComparatorBegin.java rename to src/main/java/presenter/algorithms/Comparators/YOrderLineComparatorBegin.java index 6686887..e6999ce 100644 --- a/src/main/java/Presenter/Algorithms/Comparators/YOrderLineComparatorBegin.java +++ b/src/main/java/presenter/algorithms/Comparators/YOrderLineComparatorBegin.java @@ -1,6 +1,7 @@ -package Presenter.Algorithms.Comparators; +package presenter.algorithms.Comparators; + +import model.Line; -import Model.Line; import java.util.Comparator; /** @@ -12,8 +13,8 @@ import java.util.Comparator; */ public class YOrderLineComparatorBegin implements Comparator { - @Override - public int compare(Line o1, Line o2) { + @Override + public int compare(Line o1, Line o2) { // if (o1.getY1() == o2.getY1()) { // if (o1.getX1() <= o2.getX1()) { // return -1; @@ -25,6 +26,6 @@ public class YOrderLineComparatorBegin implements Comparator { // } else { // return 1; // } - return o1.getY1().compareTo(o2.getY1()); - } + return o1.getY1().compareTo(o2.getY1()); + } } \ No newline at end of file diff --git a/src/main/java/Presenter/Algorithms/Comparators/YOrderLineComparatorEnd.java b/src/main/java/presenter/algorithms/Comparators/YOrderLineComparatorEnd.java similarity index 75% rename from src/main/java/Presenter/Algorithms/Comparators/YOrderLineComparatorEnd.java rename to src/main/java/presenter/algorithms/Comparators/YOrderLineComparatorEnd.java index bdf72e5..704231f 100644 --- a/src/main/java/Presenter/Algorithms/Comparators/YOrderLineComparatorEnd.java +++ b/src/main/java/presenter/algorithms/Comparators/YOrderLineComparatorEnd.java @@ -1,6 +1,7 @@ -package Presenter.Algorithms.Comparators; +package presenter.algorithms.Comparators; + +import model.Line; -import Model.Line; import java.util.Comparator; /** @@ -12,8 +13,8 @@ import java.util.Comparator; */ public class YOrderLineComparatorEnd implements Comparator { - @Override - public int compare(Line o1, Line o2) { + @Override + public int compare(Line o1, Line o2) { // if (o1.getY2() == o2.getY2()) { // if (o1.getX2() <= o2.getX2()) { // return -1; @@ -25,6 +26,6 @@ public class YOrderLineComparatorEnd implements Comparator { // } else { // return 1; // } - return o1.getY2().compareTo(o2.getY2()); - } + return o1.getY2().compareTo(o2.getY2()); + } } diff --git a/src/main/java/Presenter/Algorithms/FastElementSelector.java b/src/main/java/presenter/algorithms/FastElementSelector.java similarity index 71% rename from src/main/java/Presenter/Algorithms/FastElementSelector.java rename to src/main/java/presenter/algorithms/FastElementSelector.java index 5a2a26f..9c96ccf 100644 --- a/src/main/java/Presenter/Algorithms/FastElementSelector.java +++ b/src/main/java/presenter/algorithms/FastElementSelector.java @@ -1,6 +1,4 @@ -package Presenter.Algorithms; - -import Presenter.Presenter; +package presenter.algorithms; import java.util.ArrayList; import java.util.Collections; @@ -12,43 +10,39 @@ import java.util.Random; public class FastElementSelector { /** - * * @param a * @param i * @return */ public static Double randomizedSelect(ArrayList a, double i) { int start = 0; - int end = a.size()-1; + int end = a.size() - 1; - if (i >= end+1){ + if (i >= end + 1) { return a.get(end); } - while(true){ - - if(start == end){ + while (true) { + if (start >= end) { return a.get(start); } int q = randomizedPartition(a, start, end); - int k = q-start+1; + int k = q - start + 1; - if(i == k){ + if (i == k) { return a.get(q); - } - else{ - if(i a, int start, int end) { Double x = a.get(end); int i = start - 1; - for (int j = start; j <= end-1; j++) { + for (int j = start; j <= end - 1; j++) { if (a.get(j) <= x) { i++; Collections.swap(a, i, j); } } - Collections.swap(a, i+1, end); - return i+1; + Collections.swap(a, i + 1, end); + return i + 1; } } diff --git a/src/main/java/presenter/algorithms/IntersectionCounter.java b/src/main/java/presenter/algorithms/IntersectionCounter.java new file mode 100644 index 0000000..adc8ef9 --- /dev/null +++ b/src/main/java/presenter/algorithms/IntersectionCounter.java @@ -0,0 +1,268 @@ +package presenter.algorithms; + +import model.*; +import presenter.algorithms.Comparators.YOrderLineComparatorBegin; +import presenter.algorithms.Comparators.YOrderLineComparatorEnd; + +import java.util.*; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 18.06.2017. + */ +public class IntersectionCounter { + + private HashMap dictionaryTO; + private HashMap dictionaryBACK; + private ArrayList substituted; + private ArrayList inversions; + private List set; + + //indexieren der Punkte damit die schnittpunkte berechnet werden können + private HashMap secondaryDictionaryTO; + private HashMap secondaryDictionaryBACK; + private ArrayList umin; + + /** + * Berechnet die Inversionen zwischen zwei Listen mit Integer Werten. Diese Methode dient als + * Wrapper Methode. Die Logik steht in der countInversions Funktion. + * + * @param a Liste + * @param b Liste + * @return Anzahl an Inversionen + */ + public int run(List a, List b) { + + dictionaryTO = new HashMap<>(); + dictionaryBACK = new HashMap<>(); + substituted = new ArrayList<>(); + inversions = new ArrayList<>(); + + ArrayList temp = new ArrayList<>(); + + temp.addAll(a); + + for (int i = 0; i < a.size(); i++) { + dictionaryTO.put(a.get(i), i + 1); + dictionaryBACK.put(i + 1, a.get(i)); + } + + for (int j = 0; j < b.size(); j++) { + substituted.add(dictionaryTO.get(b.get(j))); + } + + int ret = countInversions(substituted, 0, substituted.size() - 1, temp); + + return ret; + } + + /** + * Wrapper Methode um herauszufinden wieviele Inversionen zwischen den Schnittpunkten der Werte + * in der Liste und den Endpunkten des Intervalls entstehen. + * + * @param set Liste mit Werten (m,b) um Schnittpunkte zu berechnen + * @param interval Interval + * @return Anzahl an Inversionen + */ + public int run(List set, Interval interval) { + ArrayList listA = new ArrayList<>(); + ArrayList listB = new ArrayList<>(); + + prepareData(set, interval, listA, listB); + return run(listA, listB); + } + + /** + * Methode die, die Daten für die Funktion run vorbereitet. Es werden die Schnittpunkte + * bzgl. der unteren und oberen Grenze des Intervals und den Werten der Liste (m,b) berechnet. Diese + * Werte haben die selbe x Koordinate aber verschiedene y Koordinaten. + * + * @param set Liste mit Werten m,b + * @param interval Interval + * @param listA Schnittpunkte bzgl. unteren Grenze + * @param listB Schnittpunkte bzgl. oberen Grenze + */ + private void prepareData(List set, Interval interval, ArrayList listA, + ArrayList listB) { + secondaryDictionaryTO = new HashMap<>(); + secondaryDictionaryBACK = new HashMap<>(); + this.set = set; + umin = new ArrayList<>(); + Line tmpLine; + + for (Line p : set) { + //vertauscht das Point standardmäßig die x lexikografische Ordnung betrachtet + tmpLine = new Line(p.getM(), p.getM(), interval.getLower() * p.getM() + p.getB(), + interval.getUpper() * p.getM() + p.getB()); + //wird benötigt um späer die Schnittpunkte ermitteln zu können + tmpLine.setB(p.getB()); + tmpLine.setM(p.getM()); + umin.add(tmpLine); + } + + for (int i = 0; i < umin.size(); i++) { + secondaryDictionaryTO.put(umin.get(i), i); + secondaryDictionaryBACK.put(i, this.set.get(i)); + } + + Collections.sort(umin, new YOrderLineComparatorBegin()); + for (Line q : umin) { + listA.add(secondaryDictionaryTO.get(q)); + } + + Collections.sort(umin, new YOrderLineComparatorEnd()); + for (Line q : umin) { + listB.add(secondaryDictionaryTO.get(q)); + } + + } + + + /** + * Angepasster Merge-Sort Algorithmus. + * Die Funktion bekommt neben den standard Parametern zusätzlich eine Liste mit Elementen + * die als Groundtruth dienen. + * + * @param a Eingabefeld mit den Elementen die überprüft werden sollen. + * @param start Startpunkt des Eingabefeldes. + * @param end Endpunkt des Eingabefeldes. + * @param aux Temporäres Array das beim Mergen eine Kopie des original Arrays ist. + * @return Anzahl der inversionen zwischen a und aux. + */ + public int countInversions(List a, int start, int end, List aux) { + if (start >= end) { + return 0; + } + int invCount = 0; + int mid = start + (end - start) / 2; + int invCountLeft = countInversions(a, start, mid, aux); // divide and conquer + int invCountRight = countInversions(a, mid + 1, end, aux); // divide and conquer + invCount += (invCountLeft + invCountRight); + for (int i = start; i <= end; i++) { + aux.set(i, a.get(i)); + } + int left = start; + int right = mid + 1; + int index = start; + //hier beginnt das merging + //iteriere über die Teillisten + //Two-way Merge - Knuth Vol 3 The Art of Computer Programming - + while (left <= mid && right <= end) { + //wenn die linke Teilliste das kleinere Element besitzt kopiere + //das Element in das neue Array + if (aux.get(left) < aux.get(right)) { + a.set(index++, aux.get(left++)); + } else { + //merke die inversionspaare + for (int i = left; i <= mid; i++) { + // System.out.println(aux.get(i)+" -- "+ aux.get(right)); + inversions.add(new Pair(aux.get(i), aux.get(right))); + } + a.set(index++, aux.get(right++)); + invCount += mid - left + 1; // number of inversions for aux[right] + } + } + while (left <= mid) { + a.set(index++, aux.get(left++)); + } + // no need to copy over remaining aux[right++] because they are already inside a + return invCount; + } + + /** + * Diese Methode liefert nur nach dem Ausführen der run Funktion Sinnvolle Werte. + * + * @return Map mit Schnittpunkt Paaren. + */ + public HashMap> getIntersectionLinePairs() { + ArrayList result = new ArrayList<>(); + HashMap> ret = new HashMap<>(); + + for (int i = 0; i < inversions.size(); i++) { + result.add(new Pair(dictionaryBACK.get(inversions.get(i).getP1()), + dictionaryBACK.get(inversions.get(i).getP2()))); + } + ArrayList linePairs; + + for (Pair p : result) { + Line l1 = secondaryDictionaryBACK.get(p.getP1()); + Line l2 = secondaryDictionaryBACK.get(p.getP2()); + if (ret.get(l2) == null) { + linePairs = new ArrayList<>(); + } else { + linePairs = ret.get(l2); + } + linePairs.add(l1); + ret.put(l2, linePairs); + + //Symetrie + if (ret.get(l1) == null) { + linePairs = new ArrayList<>(); + } else { + linePairs = ret.get(l1); + } + linePairs.add(l2); + ret.put(l1, linePairs); + } + /*System.out.println("----------------------------------------------------------"); + for (Line outerLine : ret.keySet()){ + System.out.println("Linie: "+outerLine); + for (Line innerLine : ret.get(outerLine)){ + System.out.println("\t\t -> "+innerLine); + } + } + System.out.println("----------------------------------------------------------");*/ + + return ret; + } + + /** + * Diese Methode liefert nur nach dem Ausführen der run Funktion Sinnvolle Werte. + */ + public void calculateIntersectionAbscissas(LineModel model) { + ArrayList result = new ArrayList<>(); + + for (int i = 0; i < inversions.size(); i++) { + result.add(new Pair(dictionaryBACK.get(inversions.get(i).getP1()), + dictionaryBACK.get(inversions.get(i).getP2()))); + } + + for (Pair p : result) { + Line line = secondaryDictionaryBACK.get(p.getP1()); + Line sampledLine = secondaryDictionaryBACK.get(p.getP2()); + if (!line.equals(sampledLine)) { + double intersection = (line.getB() - sampledLine.getB()) / (sampledLine.getM() - line.getM()); + double yintercept = sampledLine.getM() * intersection + sampledLine.getB(); + model.addNode(new Point(intersection, yintercept)); + } + } + + } + + /** + * Berechnet die Schnittpunkte zwischen einer gegebenen Gerade und einer Menge an Geraden. + * + * @param set Menge an Geraden + * @param sampledLine eine spezielle Gerade + * @return Liste mit x Koordinaten der Schnittpunkte + */ + public ArrayList calculateIntersectionAbscissas(ArrayList set, Line sampledLine) { + LinkedList lines = new LinkedList<>(set); + ArrayList intersections = new ArrayList<>(); + double intersection; + + for (Line line : lines) { + if (line != sampledLine) { + intersection = (line.getB() - sampledLine.getB()) / (sampledLine.getM() - line.getM()); + intersections.add(intersection); + } + } + + return intersections; + } + + +} diff --git a/src/main/java/presenter/algorithms/LeastMedianOfSquaresEstimator.java b/src/main/java/presenter/algorithms/LeastMedianOfSquaresEstimator.java new file mode 100644 index 0000000..42d8218 --- /dev/null +++ b/src/main/java/presenter/algorithms/LeastMedianOfSquaresEstimator.java @@ -0,0 +1,478 @@ +package presenter.algorithms; + +import model.Interval; +import model.Line; +import model.Point; +import presenter.Presenter; + +import java.util.*; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 28.05.2017. + */ +public class LeastMedianOfSquaresEstimator extends Observable implements Algorithm { + + + private Presenter presenter; + + private LinkedList set = new LinkedList<>(); + private LinkedList intersections = new LinkedList<>(); + private IntersectionCounter invCounter = new IntersectionCounter(); + private int n; + private double quantileError; + private int kPlus; + private int kMinus; + private PriorityQueue intervals; + private Interval subSlabU1; + private Interval subSlabU2; + private Line sigmaMin; + private double heightsigmaMin; + private Double intersectionsPoint; + private Double constant = 0.5; + + private Double slope; + private Double yInterception; + + public LeastMedianOfSquaresEstimator(LinkedList set, LinkedList intersections, + Presenter presenter) { + this.set = set; + this.intersections = intersections; + + //(1.) Let n <- |S|; q+ <- q; q- <- q+ * (1 - quantileError);.... + n = set.size(); + double quantile = 0.5; + double qPlus = quantile; + quantileError = 0.1; + double qMinus = qPlus * (1 - quantileError); + kMinus = (int) Math.ceil(n * qMinus); + kPlus = (int) Math.ceil(n * qPlus); + this.presenter = presenter; + } + + public LeastMedianOfSquaresEstimator(LinkedList set, LinkedList intersections) { + this(set, intersections, null); + } + + /** + * + */ + public void run() { + + //(2.) Let U <- (-inf, inf) be the initial active intervals... + Comparator comparator = (o1, o2) -> { + if (o1.getDistance() < o2.getDistance()) { + return -1; + } + if (o1.getDistance() > o2.getDistance()) { + return 1; + } else { + return 0; + } + }; + intervals = new PriorityQueue<>(comparator); + intervals.add(new Interval(-100000, 100000)); + heightsigmaMin = Double.MAX_VALUE; + LinkedList tmpIntersections = intersections; + + //(3.) Apply the following steps as long as the exists active intervals + boolean active = true; + Interval interval; + while (!this.intervals.isEmpty()) { + interval = this.intervals.peek(); + if (interval.getActivity()) { + //(a.) Select any active Interval and calc. the inversions + int numberOfIntersections = countInversions(interval); + + //(b.) apply plane sweep + if ((constant * n) >= numberOfIntersections) { + sigmaMin = planeSweep(interval); + } else { + //(c.) otherwise.... + // get random intersections point... + Collections.shuffle(tmpIntersections, new Random()); + for (int i = 0; i < tmpIntersections.size(); i++) { + if (tmpIntersections.get(i).getX() > interval.getLower() + && tmpIntersections.get(i).getX() < interval.getUpper()) { + intersectionsPoint = tmpIntersections.get(i).getX(); + break; + } else { + intersectionsPoint = null; + } + } + + if (intersectionsPoint != null) { + splitActiveSlab(intersectionsPoint, interval); + //(d.) this may update sigma min + upperBound(intersectionsPoint); + //(e.) for i={1,2}, call lower bound(Ui) + lowerBound(subSlabU1); + lowerBound(subSlabU2); + + if (subSlabU1.getActivity()) { + this.intervals.add(subSlabU1); + } + if (subSlabU2.getActivity()) { + this.intervals.add(subSlabU2); + } + + } else { + this.intervals.poll(); + } + } + + + } else { + this.intervals.remove(interval); + } + } + } + + /** + * @param interval + * @return + */ + public int countInversions(Interval interval) { + + int numberOfInversions = 0; + // debug + //for (int i=0;i xQueue = new ArrayList<>(); + for (Point point : intersections) { + if (point.getX() >= interval.getLower() && point.getX() < interval.getUpper()) { + xQueue.add(point); + } + } + Collections.sort(xQueue); + + Line bracelet = sigmaMin; + double heightOfBracelet = heightsigmaMin; + + for (Point current : xQueue) { + Double[] currentBracelet = calcKMinusBracelet(current, kMinus); + + if (currentBracelet == null) { + continue; + } else if (currentBracelet[0] < heightOfBracelet) { + heightOfBracelet = currentBracelet[0]; + bracelet = new Line(current.getX(), current.getX(), currentBracelet[1], currentBracelet[2]); + } + } + + interval.setActivity(false); + return bracelet; + } + + /** + * Diese Methode spaltet den aktiven Interval an der x Koordinate point. Es werden zwei neue Slabs + * erzeugt. + * + * @param point x Koordinate an der, der Split geschieht. + */ + public void splitActiveSlab(double point, Interval active) { + subSlabU1 = new Interval(active.getLower() + 0.01, point); + subSlabU2 = new Interval(point, active.getUpper()); + + this.intervals.remove(active); + } + + /** + * @param point + */ + public void upperBound(double point) { + + double height = heightsigmaMin; + double tmpHeight; + ArrayList sortedLineSequence = getEjValues(point); + + int itnbr = ((n - kMinus) + 1); + for (int i = 0; i < itnbr; i++) { + tmpHeight = sortedLineSequence.get((i + kMinus) - 1) - sortedLineSequence.get(i); + if (tmpHeight < height) { + height = tmpHeight; + } + + if (height < heightsigmaMin) { + heightsigmaMin = height; + if (sigmaMin != null) { + sigmaMin.setEndPoints(point, sortedLineSequence.get(i) + , point, sortedLineSequence.get((i + kMinus) - 1)); + } else { + sigmaMin = new Line(point, point, sortedLineSequence.get(i), + sortedLineSequence.get((i + kMinus) - 1)); + } + } + } + + } + + /** + * @param pslab + * @return + */ + public void lowerBound(Interval pslab) { + + int[] alpha = new int[n]; + int[] beta = new int[n]; + int strictlyGreater = 0; + + //Teil I. + ArrayList umaxList; + ArrayList uminList; + + //y koordinaten der Schnittpunkte + ArrayList lines = new ArrayList<>(); + for (Line p : set) { + lines.add( + new Line(pslab.getLower(), pslab.getUpper(), ((pslab.getLower() * p.getM()) + p.getB()), + ((pslab.getUpper() * p.getM()) + p.getB()))); + } + + umaxList = getEjValues(pslab.getUpper()); + uminList = getEjValues(pslab.getLower()); + + for (int i = 0; i < n; i++) { + Line level = new Line(pslab.getLower(), pslab.getUpper(), uminList.get(i), umaxList.get(i)); + for (Line line : lines) { + if ((line.getY1() < level.getY1()) && (line.getY2() < level.getY2())) { + alpha[i]++; + } + + if ((line.getY1() > level.getY1()) && (line.getY2() > level.getY2())) { + strictlyGreater++; + } + } + beta[i] = n - (alpha[i] + strictlyGreater); + strictlyGreater = 0; + } + //TEST der Alpha und Beta werte, siehe JUnit Test + //for (int i=0;i= n) { + //System.out.println("i: "+i+", j:"+j+". ungültig"); + pslab.setActivity(false); + break; + } else { + h = Math.min(Math.abs(uminList.get(j) - uminList.get(i)), + Math.abs(umaxList.get(j) - umaxList.get(i))); + double error = 0.01; + if (((1 + error) * h) < heightsigmaMin) { + //System.out.println("h: "+ h +" ist kleiner als height(sigmaMin): "+heightsigmaMin); + pslab.setActivity(true); + return; + } + } + i = 0; + } + + } + + /** + * Berechnet die Schnittpunkte der Geraden und der vertikalen Gerade u. Im paper sind diese Werte + * als e_j Werte bekannt. + * + * @param u vertikale Gerade + * @return Liste der Schnittpunkte (da u bekannt werden nur die y Werte zurück gegeben) + */ + public ArrayList getEjValues(double u) { + + ArrayList ret = new ArrayList<>(); + + for (Line p : set) { + ret.add((p.getM() * u) + p.getB()); + } + + Collections.sort(ret); + + return ret; + } + + /** + * Die Funktion berechnet anhand einer vertikalen Gerade x = px das sogenannte kleinste kMinus + * Bracelet. Mit anderen Worten es wird eine vertikale Teilgerade berechnet die mindestens kMinus + * Geraden schneidet und dabei minimal ist. + * + * @param px Koordinate um die "vertikale Gerade" zu simulieren. + * @return Das Array enthält höhe des Bracelet, e_j und e_(j + kMinus - 1) + */ + public Double[] calcKMinusBracelet(Point px, int kMinusValue) { + + //y Koordinaten für das kMinus brecalet + LinkedList intersections = new LinkedList<>(); + for (Line line : set) { + intersections.add((px.getX() * line.getM()) + line.getB()); + } + if (intersections.size() >= kMinusValue) { + Collections.sort(intersections); + double height = Math.abs(intersections.get(0) - intersections.get(0 + kMinusValue - 1)); + Double[] ret = {height, intersections.get(0), intersections.get(0 + kMinusValue - 1)}; + return ret; + } else { + return null; + } + + } + + @Override + public void getResult() { + if (presenter != null) { + setChanged(); + double m = (getSigmaMin().getX2() + getSigmaMin().getX1()) * 0.5; + double b = (getSigmaMin().getY2() + getSigmaMin().getY1()) * -0.5; + + slope = m; + yInterception = b; + + String[] result = {"lms", m + "", b + ""}; + notifyObservers(result); + } else { + double m = (getSigmaMin().getX2() + getSigmaMin().getX1()) * 0.5; + double b = (getSigmaMin().getY2() + getSigmaMin().getY1()) * -0.5; + + slope = m; + yInterception = b; + } + } + + /** + * Im Allgemeinen werden keine Getter und Setter Methoden benötigt aber sie sind nützlich bei den + * JUnit Testfällen. + */ + + public LinkedList getSet() { + return set; + } + + public void setSet(LinkedList set) { + this.set = set; + } + + public LinkedList getIntersections() { + return intersections; + } + + public void setIntersections(LinkedList intersections) { + this.intersections = intersections; + } + + public int getN() { + return n; + } + + public void setN(int n) { + this.n = n; + } + + public double getQuantileError() { + return quantileError; + } + + public void setQuantileError(double quantileError) { + this.quantileError = quantileError; + } + + public int getkPlus() { + return kPlus; + } + + public void setkPlus(int kPlus) { + this.kPlus = kPlus; + } + + public int getkMinus() { + return kMinus; + } + + public void setkMinus(int kMinus) { + this.kMinus = kMinus; + } + + public Interval getSubSlabU1() { + return subSlabU1; + } + + public void setSubSlabU1(Interval subSlabU1) { + this.subSlabU1 = subSlabU1; + } + + public Interval getSubSlabU2() { + return subSlabU2; + } + + public void setSubSlabU2(Interval subSlabU2) { + this.subSlabU2 = subSlabU2; + } + + public Line getSigmaMin() { + return sigmaMin; + } + + public void setSigmaMin(Line sigmaMin) { + this.sigmaMin = sigmaMin; + } + + public double getHeightsigmaMin() { + return heightsigmaMin; + } + + public void setHeightsigmaMin(double heightsigmaMin) { + this.heightsigmaMin = heightsigmaMin; + } + + public double getIntersectionsPoint() { + return intersectionsPoint; + } + + public void setIntersectionsPoint(double intersectionsPoint) { + this.intersectionsPoint = intersectionsPoint; + } + + public Double getConstant() { + return constant; + } + + public void setConstant(Double constant) { + this.constant = constant; + } + + public Double getSlope() { + return slope; + } + + public Double getyInterception() { + return yInterception; + } +} diff --git a/src/main/java/presenter/algorithms/RandomSampler.java b/src/main/java/presenter/algorithms/RandomSampler.java new file mode 100644 index 0000000..714f4c1 --- /dev/null +++ b/src/main/java/presenter/algorithms/RandomSampler.java @@ -0,0 +1,56 @@ +package presenter.algorithms; + +import model.Line; +import model.Point; + +import java.util.ArrayList; +import java.util.concurrent.ThreadLocalRandom; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 26.06.2017. + */ +public class RandomSampler { + + /** + * Diese Methode liefert eine r Elementige zufällige Stichprobe an Geraden. + * + * @param set Die gesammtmenge der Geraden aus denen gewählt werden soll + * @param r Anzahl der zu wählenden Geraden + * @return r Elementige zufällige Stichprobe an Geraden + */ + public static ArrayList run(ArrayList set, Double r, Integer indexOfEnd) { + + ArrayList sampledLines = new ArrayList<>(); + + for (int i = 0; i < r; i++) { + sampledLines.add(set.get(ThreadLocalRandom.current().nextInt(0, indexOfEnd))); + } + + return sampledLines; + } + + /** + * Diese Methode liefert eine r Elementige zufällige Stichprobe van Schnittpunkten. + * + * @param set Die gesammtmenge der Geraden aus denen gewählt werden soll + * @param r Anzahl der zu wählenden Geraden + * @return r Elementige zufällige Stichprobe an Schnittpunkten + */ + public static ArrayList run(ArrayList set, Double r) { + + ArrayList sampledLines = new ArrayList<>(); + Integer indexOfEnd = set.size(); + + for (int i = 0; i < r; i++) { + Double px = set.get(ThreadLocalRandom.current().nextInt(0, indexOfEnd)).getX(); + if (!sampledLines.contains(px)) + sampledLines.add(px); + } + + return sampledLines; + } +} diff --git a/src/main/java/presenter/algorithms/RepeatedMedianEstimator.java b/src/main/java/presenter/algorithms/RepeatedMedianEstimator.java new file mode 100644 index 0000000..7b87e08 --- /dev/null +++ b/src/main/java/presenter/algorithms/RepeatedMedianEstimator.java @@ -0,0 +1,459 @@ +package presenter.algorithms; + +import model.Interval; +import model.Line; +import presenter.Presenter; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Observable; +import java.util.concurrent.ThreadLocalRandom; + + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 28.05.2017. + */ +public class RepeatedMedianEstimator extends Observable implements Algorithm { + + private Presenter presenter; + private LinkedList set; + private HashMap> linePairs; + private HashMap medianIntersections = new HashMap<>(); + private HashMap> intersectionAbscissas = new HashMap<>(); + private Interval interval; + + //in der Literatur als L_i, C_i, und R_i bekannt + private ArrayList countLeftSlab; + private ArrayList countCenterSlab; + private ArrayList countRightSlab; + + //die Mengen L,C und R + private ArrayList linesInLeftSlab; + private ArrayList linesInCenterSlab; + private ArrayList linesInRightSlab; + + private Double r; + private Integer n; + private Double k; + private Double kLow; + private Double kHigh; + private Double beta; + + private Double thetaLow; + private Double thetaHigh; + + private Double slope; + private Double yInterception; + + + public RepeatedMedianEstimator(LinkedList set, Presenter presenter) { + this.set = set; + this.presenter = presenter; + interval = new Interval(-10000, 10000); + n = set.size(); + beta = 0.5; + countLeftSlab = new ArrayList<>(); + countCenterSlab = new ArrayList<>(); + countRightSlab = new ArrayList<>(); + + for (int i = 0; i < n; i++) { + countLeftSlab.add(0d); + countRightSlab.add(0d); + countCenterSlab.add(n - 1.0); + intersectionAbscissas.put(set.get(i), new ArrayList<>()); + } + + linesInLeftSlab = new ArrayList<>(); + linesInCenterSlab = new ArrayList<>(set); + linesInRightSlab = new ArrayList<>(); + linePairs = new HashMap<>(); + } + + public RepeatedMedianEstimator(LinkedList set) { + this(set, null); + } + + /** + * + */ + public void run() { + + while (linesInCenterSlab.size() != 1) { + n = linesInCenterSlab.size(); + r = Math.ceil(Math.pow(n, beta)); + ArrayList lines = RandomSampler.run(linesInCenterSlab, r, linesInCenterSlab.size()); + + + //For each Sampled Line, compute its median intersection abscissa + ArrayList medianIntersectionAbscissas = new ArrayList<>(); + for (Line l : lines) { + Double abscissa = estimateMedianIntersectionAbscissas(l); + medianIntersections.put(l, abscissa); + medianIntersectionAbscissas.add(abscissa); + } + + //rank of the repeated median in C + k = Math.max(1, Math.min(set.size(), (Math.ceil(n * 0.5) - linesInLeftSlab.size()))); + + //compute k_lo and k_hi + computeSlabBorders(); + + + // if (medianIntersectionAbscissas.size() < kLow || medianIntersectionAbscissas.size() sampleLines(ArrayList set, Double r) { + + ArrayList sampledLines = new ArrayList<>(); + + for (int i = 0; i < r; i++) { + sampledLines.add(set.get(ThreadLocalRandom.current().nextInt(0, linesInCenterSlab.size()))); + } + + return sampledLines; + } + + /** + * @param sampledLine + * @return + */ + public Double estimateMedianIntersectionAbscissas(Line sampledLine) { + + Integer index = Integer.parseInt(sampledLine.getId()); + ArrayList intersections = new ArrayList<>(); + double intersection; + + IntersectionCounter intersectionCounter = new IntersectionCounter(); + intersections = intersectionCounter.calculateIntersectionAbscissas(linesInCenterSlab, sampledLine); + + //Collections.sort(intersections); + //double ki = Math.ceil((n - 1) / 2) - countLeftSlab.get(index); + //double i = (Math.ceil((Math.sqrt(n) * ki) / countCenterSlab.get(index))); + double ki = Math.ceil((n - 1) / 2) - FastElementSelector.randomizedSelect(countLeftSlab, index); + double i = (Math.ceil((Math.sqrt(n) * ki) / FastElementSelector.randomizedSelect(countCenterSlab, index))); + int accessIndex; + if (i < 0) + accessIndex = 0; + else if (i >= intersections.size()) + accessIndex = intersections.size() - 1; + else + accessIndex = (int) i; + + //System.out.println(accessIndex); + + //return intersections.get(accessIndex); + return FastElementSelector.randomizedSelect(intersections, accessIndex); + } + + /** + * + */ + public void computeSlabBorders() { + kLow = Math + .max(1, Math.floor( + ((r * k) / (linesInCenterSlab.size())) + - ((3 * Math.sqrt(r)) / (2)) + ) + ); + kHigh = Math + .min(r, Math.floor( + ((r * k) / (linesInCenterSlab.size())) + + ((3 * Math.sqrt(r)) / (2)) + ) + ); + } + + + /** + * + */ + public void countNumberOfIntersectionsAbscissas() { + + for (Line line : linesInCenterSlab) { + ArrayList intersections = intersectionAbscissas.get(line); + Integer index = Integer.parseInt(line.getId()); + int left = 0; + int center = 0; + int right = 0; + + for (Double intersection : intersections) { + if (intersection <= thetaLow) { + left++; + } else if (intersection > thetaLow && intersection <= thetaHigh) { + center++; + } else if (intersection > thetaHigh) { + right++; + } + } + + //System.out.println("Linie: "+line.getId()+"\tLeft: "+left+"\t Center: "+center+"\t Right: "+right); + countLeftSlab.set(index, (double) left); + countCenterSlab.set(index, (double) center); + countRightSlab.set(index, (double) right); + } + + } + + /** + * + */ + public void contractIntervals() { + for (int i = 0; i < linesInCenterSlab.size(); i++) { + + double left = countLeftSlab.get(i); + double center = countCenterSlab.get(i); + double right = countRightSlab.get(i); + + double max = Math.max(left, Math.max(center, right)); + + if (left == max) { + linesInLeftSlab.add(linesInCenterSlab.get(i)); + linesInCenterSlab.remove(i); + } else if (right == max) { + linesInRightSlab.add(linesInCenterSlab.get(i)); + linesInCenterSlab.remove(i); + } + // if (medianIntersections.get(linesInCenterSlab.get(i)) != null) { + // if (medianIntersections.get(linesInCenterSlab.get(i)) <= thetaLow) { + // linesInLeftSlab.add(linesInCenterSlab.get(i)); + // linesInCenterSlab.remove(i); + // countLeftSlab.set(i, countLeftSlab.get(i) + 1); + // countCenterSlab.set(i, countCenterSlab.get(i) - 1); + // } else if (medianIntersections.get(linesInCenterSlab.get(i)) > thetaHigh) { + // linesInRightSlab.add(linesInCenterSlab.get(i)); + // linesInCenterSlab.remove(i); + // countRightSlab.set(i, countRightSlab.get(i) + 1); + // countCenterSlab.set(i, countCenterSlab.get(i) - 1); + // } + // } + // } + // + } + + //wähle C als C + if (linesInLeftSlab.size() < Math.ceil(n / 2) && Math.ceil(n / 2) <= linesInLeftSlab.size() + linesInCenterSlab.size()) { + interval.setLower(thetaLow + 0.1); + interval.setUpper(thetaHigh); + } + // wähle L als C + else if (Math.ceil(n / 2) <= linesInLeftSlab.size()) { + interval.setUpper(thetaLow); + } + //wähle R als C + else if (linesInLeftSlab.size() + linesInCenterSlab.size() < Math.ceil(n / 2) && Math.ceil(n / 2) <= (linesInLeftSlab.size() + linesInCenterSlab.size() + linesInRightSlab.size())) { + interval.setLower(thetaHigh - 0.1); + } + } + + @Override + public void getResult() { + if (presenter != null) { + setChanged(); + double m = thetaLow; + double b = (-1) * ( + (linesInCenterSlab.get(0).getM() * (thetaLow)) + linesInCenterSlab.get(0) + .getB()); + + slope = m; + yInterception = b; + String[] result = new String[]{"rm", m + "", b + ""}; + notifyObservers(result); + } else { + double m = thetaLow; + double b = (-1) * ((linesInCenterSlab.get(0).getM() * (thetaLow)) + linesInCenterSlab.get(0).getB()); + slope = m; + yInterception = b; + } + } + + /******************************************************************************************************************* + * Getter und Setter Methoden + ******************************************************************************************************************/ + public LinkedList getSet() { + return set; + } + + public void setSet(LinkedList set) { + this.set = set; + } + + public HashMap> getLinePairs() { + return linePairs; + } + + public void setLinePairs(HashMap> linePairs) { + this.linePairs = linePairs; + } + + public HashMap getMedianIntersections() { + return medianIntersections; + } + + public void setMedianIntersections(HashMap medianIntersections) { + this.medianIntersections = medianIntersections; + } + + public HashMap> getIntersectionAbscissas() { + return intersectionAbscissas; + } + + public void setIntersectionAbscissas( + HashMap> intersectionAbscissas) { + this.intersectionAbscissas = intersectionAbscissas; + } + + public Interval getInterval() { + return interval; + } + + public void setInterval(Interval interval) { + this.interval = interval; + } + + public ArrayList getCountLeftSlab() { + return countLeftSlab; + } + + public void setCountLeftSlab(ArrayList countLeftSlab) { + this.countLeftSlab = countLeftSlab; + } + + public ArrayList getCountCenterSlab() { + return countCenterSlab; + } + + public void setCountCenterSlab(ArrayList countCenterSlab) { + this.countCenterSlab = countCenterSlab; + } + + public ArrayList getCountRightSlab() { + return countRightSlab; + } + + public void setCountRightSlab(ArrayList countRightSlab) { + this.countRightSlab = countRightSlab; + } + + public ArrayList getLinesInLeftSlab() { + return linesInLeftSlab; + } + + public void setLinesInLeftSlab(ArrayList linesInLeftSlab) { + this.linesInLeftSlab = linesInLeftSlab; + } + + public ArrayList getLinesInCenterSlab() { + return linesInCenterSlab; + } + + public void setLinesInCenterSlab(ArrayList linesInCenterSlab) { + this.linesInCenterSlab = linesInCenterSlab; + } + + public ArrayList getLinesInRightSlab() { + return linesInRightSlab; + } + + public void setLinesInRightSlab(ArrayList linesInRightSlab) { + this.linesInRightSlab = linesInRightSlab; + } + + public Double getR() { + return r; + } + + public void setR(Double r) { + this.r = r; + } + + public Integer getN() { + return n; + } + + public void setN(Integer n) { + this.n = n; + } + + public Double getK() { + return k; + } + + public void setK(Double k) { + this.k = k; + } + + public Double getkLow() { + return kLow; + } + + public void setkLow(Double kLow) { + this.kLow = kLow; + } + + public Double getkHigh() { + return kHigh; + } + + public void setkHigh(Double kHigh) { + this.kHigh = kHigh; + } + + public Double getBeta() { + return beta; + } + + public void setBeta(Double beta) { + this.beta = beta; + } + + public Double getThetaLow() { + return thetaLow; + } + + public void setThetaLow(Double thetaLow) { + this.thetaLow = thetaLow; + } + + public Double getThetaHigh() { + return thetaHigh; + } + + public void setThetaHigh(Double thetaHigh) { + this.thetaHigh = thetaHigh; + } + + public Double getSlope() { + return slope; + } + + public Double getyInterception() { + return yInterception; + } +} + + diff --git a/src/main/java/Presenter/Algorithms/TheilSenEstimator.java b/src/main/java/presenter/algorithms/TheilSenEstimator.java similarity index 92% rename from src/main/java/Presenter/Algorithms/TheilSenEstimator.java rename to src/main/java/presenter/algorithms/TheilSenEstimator.java index dfa085d..cf2b046 100644 --- a/src/main/java/Presenter/Algorithms/TheilSenEstimator.java +++ b/src/main/java/presenter/algorithms/TheilSenEstimator.java @@ -1,11 +1,10 @@ -package Presenter.Algorithms; +package presenter.algorithms; -import Model.Interval; -import Model.Line; -import Model.Point; -import Presenter.Presenter; +import model.Interval; +import model.Line; +import model.Point; +import presenter.Presenter; -import com.sun.org.apache.bcel.internal.generic.FASTORE; import java.util.*; /** @@ -19,20 +18,15 @@ public class TheilSenEstimator extends Observable implements Algorithm { private final Double POSITIV_INF = 99999.0; private final Double NEGATIV_INF = -99999.0; - - + private final Double EPSILON = 0.00001; private Presenter presenter; private ArrayList setOfLines; private ArrayList setOfIntersections; private ArrayList intervalIntersections; private ArrayList sampledIntersections; - - //wird benötigt um den y Achsenabschnitt zu Berechnen private ArrayList yCoordinates; private ArrayList xCoordinates; - - //Hilfsvariablen (siehe original Paper) private Double j; private Integer jA; @@ -41,17 +35,13 @@ public class TheilSenEstimator extends Observable implements Algorithm { private Integer n; private Double N; private Integer k; - //Intervall und die temporaeren Grenzen private Interval interval; private Double aVariant; private Double bVariant; - private Double slope; private Double yInterception; - private final Double EPSILON = 0.00001; - public TheilSenEstimator(LinkedList setOfLines, LinkedList setOfIntersections, Presenter presenter) { this.presenter = presenter; @@ -64,11 +54,11 @@ public class TheilSenEstimator extends Observable implements Algorithm { this.yCoordinates = new ArrayList<>(); this.xCoordinates = new ArrayList<>(); this.N = BinomialCoeffizient.run(n, 2); - this.k = Integer.valueOf((int) (N * 0.5))-1; + this.k = Integer.valueOf((int) (N * 0.5)) - 1; } public TheilSenEstimator(LinkedList setOfLines, LinkedList setOfIntersections) { - this(setOfLines,setOfIntersections,null); + this(setOfLines, setOfIntersections, null); } /** @@ -134,9 +124,9 @@ public class TheilSenEstimator extends Observable implements Algorithm { Boolean cond1 = conda && condb; - Boolean cond2 = (higherCount-lowerCount) <= ((11 * N) / Math.sqrt(r)); + Boolean cond2 = (higherCount - lowerCount) <= ((11 * N) / Math.sqrt(r)); - return cond1 && cond2; + return (cond1 && cond2) || (aVariant == bVariant); } @@ -168,7 +158,7 @@ public class TheilSenEstimator extends Observable implements Algorithm { */ public int getOpenIntervalSize(double a, double b, ArrayList set) { int counter = 0; - for (int i=0;i a && x.getX() < b) { counter++; @@ -188,7 +178,7 @@ public class TheilSenEstimator extends Observable implements Algorithm { */ public ArrayList getOpenIntervalElements(double a, double b) { ArrayList list = new ArrayList<>(); - for (int i=0;i a && x.getX() < b) || (Math.abs(interval.getUpper() - interval.getLower())) < EPSILON) { list.add(x); @@ -207,21 +197,21 @@ public class TheilSenEstimator extends Observable implements Algorithm { ArrayList resultSt = getOpenIntervalElements(interval.getLower(), interval.getUpper()); ArrayList resultAbscissas = new ArrayList<>(); - for (Point p : resultSt){ + for (Point p : resultSt) { resultAbscissas.add(p.getX()); } - for (Point p: setOfIntersections) { + for (Point p : setOfIntersections) { yCoordinates.add(p.getY()); } int pseudoIndex = (int) getOpenIntervalSize(NEGATIV_INF, interval.getLower(), setOfIntersections); - m = FastElementSelector.randomizedSelect(resultAbscissas, k-pseudoIndex); + m = FastElementSelector.randomizedSelect(resultAbscissas, k - pseudoIndex); Set unique = new LinkedHashSet<>(yCoordinates); yCoordinates.clear(); yCoordinates.addAll(unique); - b = FastElementSelector.randomizedSelect(yCoordinates, yCoordinates.size()*0.5) * -1; + b = FastElementSelector.randomizedSelect(yCoordinates, yCoordinates.size() * 0.5) * -1; slope = m; yInterception = b; diff --git a/src/main/java/Presenter/Evaluation/EvaluateAlgorithms.java b/src/main/java/presenter/evaluation/EvaluateAlgorithms.java similarity index 79% rename from src/main/java/Presenter/Evaluation/EvaluateAlgorithms.java rename to src/main/java/presenter/evaluation/EvaluateAlgorithms.java index 34123a0..4cb901a 100644 --- a/src/main/java/Presenter/Evaluation/EvaluateAlgorithms.java +++ b/src/main/java/presenter/evaluation/EvaluateAlgorithms.java @@ -1,16 +1,17 @@ -package Presenter.Evaluation; +package presenter.evaluation; -import Model.Interval; -import Model.Line; -import Model.LineModel; -import Presenter.Algorithms.*; -import Presenter.Generator.DatasetGenerator; +import model.Interval; +import model.Line; +import model.LineModel; +import presenter.algorithms.IntersectionCounter; +import presenter.algorithms.LeastMedianOfSquaresEstimator; +import presenter.algorithms.RepeatedMedianEstimator; +import presenter.algorithms.TheilSenEstimator; +import presenter.generator.DatasetGenerator; import java.util.ArrayList; -import java.util.Arrays; import java.util.LinkedList; import java.util.Observable; -import javax.swing.JOptionPane; /** * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. @@ -41,21 +42,22 @@ public class EvaluateAlgorithms extends Observable { private int alg; /** - * Konstruktor zur Evaluation - * @param type Typ der Evaluation - * @param n Größe des Datensatzes - * @param alg 0 = lms, - * 1 = rm, - * 2 = ts, - * 3 = lms, rm, - * 4 = lms, ts, - * 5 = rm, ts, - * 6 = lms, rm, ts, + * Konstruktor zur evaluation + * + * @param type Typ der evaluation + * @param n Größe des Datensatzes + * @param alg 0 = lms, + * 1 = rm, + * 2 = ts, + * 3 = lms, rm, + * 4 = lms, ts, + * 5 = rm, ts, + * 6 = lms, rm, ts, */ - public EvaluateAlgorithms(int type, int n, int alg, String datasettyp){ + public EvaluateAlgorithms(int type, int n, int alg, String datasettyp) { this.arrangement = new LineModel(); generator = new DatasetGenerator(); - switch (datasettyp){ + switch (datasettyp) { case "Punktwolke": arrangement.setLines(generator.generateDataCloud(n)); break; @@ -83,30 +85,30 @@ public class EvaluateAlgorithms extends Observable { ArrayList result; ArrayList> multipleResults = new ArrayList<>(); - switch (type){ + switch (type) { case 0: - result = new ArrayList<>(); - //der alg der gewählt wurde - if (alg == 0) { - startLMS(); - result = getScaleDependentMeasure(arrangement.getLines(), lmsRes[0], lmsRes[1]); - sendPlotLineResults(lmsRes,0); - } else if (alg == 1) { - startRM(); - result = getScaleDependentMeasure(arrangement.getLines(), rmRes[0], rmRes[1]); - sendPlotLineResults(rmRes,1); - } else { - startTS(); - result = getScaleDependentMeasure(arrangement.getLines(), tsRes[0], tsRes[1]); - sendPlotLineResults(tsRes,2); - } + result = new ArrayList<>(); + //der alg der gewählt wurde + if (alg == 0) { + startLMS(); + result = getScaleDependentMeasure(arrangement.getLines(), lmsRes[0], lmsRes[1]); + sendPlotLineResults(lmsRes, 0); + } else if (alg == 1) { + startRM(); + result = getScaleDependentMeasure(arrangement.getLines(), rmRes[0], rmRes[1]); + sendPlotLineResults(rmRes, 1); + } else { + startTS(); + result = getScaleDependentMeasure(arrangement.getLines(), tsRes[0], tsRes[1]); + sendPlotLineResults(tsRes, 2); + } sendTableApproximationTypes(); sendTableApproximationData(result, alg); break; case 1: result = new ArrayList<>(); ArrayList lineRes; - switch (alg){ + switch (alg) { case 3: startLMS(); startRM(); @@ -121,7 +123,7 @@ public class EvaluateAlgorithms extends Observable { lineRes = new ArrayList<>(); lineRes.add(lmsRes); lineRes.add(rmRes); - sendPloteLineResults(lineRes, new Integer[]{0,1}); + sendPloteLineResults(lineRes, new Integer[]{0, 1}); break; case 4: startLMS(); @@ -137,7 +139,7 @@ public class EvaluateAlgorithms extends Observable { lineRes = new ArrayList<>(); lineRes.add(lmsRes); lineRes.add(tsRes); - sendPloteLineResults(lineRes, new Integer[]{0,2}); + sendPloteLineResults(lineRes, new Integer[]{0, 2}); break; case 5: startRM(); @@ -153,7 +155,7 @@ public class EvaluateAlgorithms extends Observable { lineRes = new ArrayList<>(); lineRes.add(rmRes); lineRes.add(tsRes); - sendPloteLineResults(lineRes, new Integer[]{1,2}); + sendPloteLineResults(lineRes, new Integer[]{1, 2}); break; case 6: startLMS(); @@ -171,7 +173,7 @@ public class EvaluateAlgorithms extends Observable { lineRes.add(lmsRes); lineRes.add(rmRes); lineRes.add(tsRes); - sendPloteLineResults(lineRes, new Integer[]{0,1,2}); + sendPloteLineResults(lineRes, new Integer[]{0, 1, 2}); break; } @@ -180,14 +182,13 @@ public class EvaluateAlgorithms extends Observable { } - } - public void sendTableApproximationData(ArrayList result, int col){ + public void sendTableApproximationData(ArrayList result, int col) { ArrayList tableInput = new ArrayList<>(); tableInput.add("eval-d"); - tableInput.add(""+col); - for (int i=0;i> result){ + public void sendTableApproximationData(ArrayList> result) { ArrayList tableInput = new ArrayList<>(); //iteration über die ApproximationsGüten -- Zeilen - for (int j=0;j<=result.get(0).size();j++){ + for (int j = 0; j <= result.get(0).size(); j++) { tableInput.add("eval-ds"); - if(j != result.get(0).size()) { + if (j != result.get(0).size()) { tableInput.add(names[type][j]); //iteration über die alg. -- Spalten @@ -223,11 +224,11 @@ public class EvaluateAlgorithms extends Observable { } - public void sendTableApproximationTypes(){ + public void sendTableApproximationTypes() { ArrayList tableInput = new ArrayList<>(); tableInput.add("eval-t"); - tableInput.add(""+0); - for (int i=0;i lines = new ArrayList<>(); lines.add("lines-res"); - lines.add(""+alg); + lines.add("" + alg); //lms res - lines.add(res[0]+""); - lines.add(res[1]+""); + lines.add(res[0] + ""); + lines.add(res[1] + ""); setChanged(); notifyObservers(lines.stream().toArray(String[]::new)); } - public void sendPloteLineResults(ArrayList res, Integer[] algs){ + public void sendPloteLineResults(ArrayList res, Integer[] algs) { ArrayList lines = new ArrayList<>(); lines.add("lines-res-mult"); - for (int i=0;i getScaledErrorBasedMeasure(LinkedList lines, Double m, Double b){ + public ArrayList getScaledErrorBasedMeasure(LinkedList lines, Double m, Double b) { ScaledErrorBasedMeasure scaledErrorBasedMeasure = new ScaledErrorBasedMeasure(lines, m, b); ArrayList ret = new ArrayList<>(); ret.add(scaledErrorBasedMeasure.mse().toString()); @@ -332,17 +333,17 @@ public class EvaluateAlgorithms extends Observable { return ret; } - private ArrayList fillPseudoResults(){ + private ArrayList fillPseudoResults() { ArrayList result = new ArrayList<>(); result.add(" "); result.add(" "); result.add(" "); result.add(" "); - return result; + return result; } - public LinkedList getData(){ + public LinkedList getData() { return arrangement.getLines(); } } diff --git a/src/main/java/presenter/evaluation/PercentageErrorBasedMeasure.java b/src/main/java/presenter/evaluation/PercentageErrorBasedMeasure.java new file mode 100644 index 0000000..05a9594 --- /dev/null +++ b/src/main/java/presenter/evaluation/PercentageErrorBasedMeasure.java @@ -0,0 +1,82 @@ +package presenter.evaluation; + +import model.Line; +import presenter.algorithms.FastElementSelector; + +import java.util.ArrayList; +import java.util.LinkedList; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 07.09.2017. + */ +public class PercentageErrorBasedMeasure { + + + private ArrayList percentageError; + + public PercentageErrorBasedMeasure(final LinkedList lines, Double m, Double b) { + + ArrayList sampson = new ArrayList<>(); + + for (Line line : lines) { + Double e = Math.pow(m * line.getM() - line.getB() + b, 2) / (Math.pow(m, 2) + 1); + sampson.add(e); + } + + percentageError = new ArrayList<>(); + + for (int j = 0; j < sampson.size(); j++) { + percentageError.add(100 * sampson.get(j) / lines.get(j).getB()); + } + } + + /* Percentege Error Approximation Measures */ + //verschiedene Eingaben für einen Alg. + public Double mape() { + double error = 0; + + for (Double d : percentageError) { + error += Math.abs(d); + } + + error /= percentageError.size(); + + return error; + } + + public Double mdape() { + + ArrayList abs = new ArrayList<>(); + + for (Double d : percentageError) { + abs.add(Math.abs(d)); + } + + return FastElementSelector.randomizedSelect(abs, abs.size() * 0.5); + } + + public Double rmspe() { + double error = 0; + + for (Double d : percentageError) { + error += Math.pow(d, 2); + } + + error /= percentageError.size(); + + return Math.sqrt(error); + } + + public Double rmdspe() { + ArrayList squares = new ArrayList(); + for (Double d : percentageError) { + squares.add(Math.pow(d, 2)); + } + + return Math.sqrt(FastElementSelector.randomizedSelect(squares, squares.size() * 0.5)); + } +} diff --git a/src/main/java/presenter/evaluation/ScaleDependentMeasure.java b/src/main/java/presenter/evaluation/ScaleDependentMeasure.java new file mode 100644 index 0000000..b78807e --- /dev/null +++ b/src/main/java/presenter/evaluation/ScaleDependentMeasure.java @@ -0,0 +1,61 @@ +package presenter.evaluation; + +import model.Line; +import presenter.algorithms.FastElementSelector; + +import java.util.ArrayList; +import java.util.LinkedList; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 07.09.2017. + */ +public class ScaleDependentMeasure { + + private ArrayList errorValues; + + public ScaleDependentMeasure(final LinkedList lines, Double m, Double b) { + //Liste mit den Fehler zu jedem Punkt + errorValues = new ArrayList<>(); + + for (Line line : lines) { + Double e = Math.pow(m * line.getM() - line.getB() + b, 2) / (Math.pow(m, 2) + 1); + errorValues.add(e); + } + } + + /* Skalierungs Abhängige Approximationsgüten */ + //unterschiedliche Alg.- auf einem Datensatz + public Double mse() { + double error = 0; + + for (Double d : errorValues) { + error += Math.pow(d, 2); + } + + error /= errorValues.size(); + + return error; + } + + public Double rmse() { + return Math.sqrt(mse()); + } + + public Double mae() { + double error = 0; + for (Double d : errorValues) { + error += Math.abs(d); + } + error /= errorValues.size(); + return error; + } + + public Double mdae() { + return FastElementSelector + .randomizedSelect(errorValues, errorValues.size() * 0.5); + } +} diff --git a/src/main/java/presenter/evaluation/ScaledErrorBasedMeasure.java b/src/main/java/presenter/evaluation/ScaledErrorBasedMeasure.java new file mode 100644 index 0000000..f41e25c --- /dev/null +++ b/src/main/java/presenter/evaluation/ScaledErrorBasedMeasure.java @@ -0,0 +1,72 @@ +package presenter.evaluation; + +import model.Line; +import presenter.algorithms.FastElementSelector; + +import java.util.ArrayList; +import java.util.LinkedList; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 07.09.2017. + */ +public class ScaledErrorBasedMeasure { + + + private ArrayList scaledError; + + public ScaledErrorBasedMeasure(final LinkedList lines, Double m, Double b) { + //Liste mit den Fehler zu jedem Punkt + ArrayList sampson = new ArrayList<>(); + + + Double denum = 0d; + for (int i = 2; i < lines.size(); i++) { + denum += Math.abs(lines.get(i).getM() - lines.get(i - 1).getM()); + } + denum *= 1 / (lines.size() - 1); + + for (Line line : lines) { + Double e = Math.pow(m * line.getM() - line.getB() + b, 2) / (Math.pow(m, 2) + 1); + sampson.add(e); + + Double val = e / (denum); + scaledError.add(val); + } + + + } + + /* Skalierungs Abhängige Approximationsgüten */ + //unterschiedliche Alg.- auf einem Datensatz + public Double mse() { + double error = 0; + for (Double d : scaledError) { + error += Math.pow(d, 2); + } + error /= scaledError.size(); + return error; + } + + public Double rmse() { + return Math.sqrt(mse()); + } + + public Double mae() { + double error = 0; + for (Double d : scaledError) { + error += Math.abs(d); + } + error /= scaledError.size(); + return error; + } + + public Double mdae() { + return FastElementSelector + .randomizedSelect(scaledError, scaledError.size() * 0.5); + } + +} diff --git a/src/main/java/Presenter/Generator/DatasetGenerator.java b/src/main/java/presenter/generator/DatasetGenerator.java similarity index 66% rename from src/main/java/Presenter/Generator/DatasetGenerator.java rename to src/main/java/presenter/generator/DatasetGenerator.java index 54399ad..fe5f3d3 100644 --- a/src/main/java/Presenter/Generator/DatasetGenerator.java +++ b/src/main/java/presenter/generator/DatasetGenerator.java @@ -1,9 +1,7 @@ -package Presenter.Generator; +package presenter.generator; -import Model.Line; +import model.Line; -import Model.Point; -import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.Observable; @@ -16,53 +14,53 @@ import java.util.Random; * @Email: a_wolf28@uni-muenster.de * @Date: 01.08.2017. */ -public class DatasetGenerator extends Observable{ +public class DatasetGenerator extends Observable { private Double m; private Double b; private Random random; - public DatasetGenerator(Double m, Double b){ + public DatasetGenerator(Double m, Double b) { this.m = m; this.b = b; random = new Random(); random.setSeed(9999); } - public DatasetGenerator(){ + public DatasetGenerator() { random = new Random(); } - public LinkedList generateDataCloud(int size){ + public LinkedList generateDataCloud(int size) { LinkedList lines = new LinkedList<>(); m = 1 + random.nextDouble(); b = random.nextDouble(); - for (int i=1;i<(size+1);i++){ + for (int i = 1; i < (size + 1); i++) { double y = (random.nextGaussian() * 100) % 100; double signal = m * i + b; signal *= -1; Line line = new Line((double) i, signal - y); - line.setId(i-1+""); + line.setId(i - 1 + ""); lines.add(line); } - String[] ret = {"generator","Es wurden "+100+" Daten generiert mit den Parametern", - "
m = "+m+"", - "
b = "+b+""}; + String[] ret = {"generator", "Es wurden " + 100 + " Daten generiert mit den Parametern", + "
m = " + m + "", + "
b = " + b + ""}; setChanged(); notifyObservers(ret); return lines; } - public LinkedList generateDataLines(int size){ + public LinkedList generateDataLines(int size) { LinkedList lines = new LinkedList<>(); return generateDataLines(lines, size); } - private LinkedList generateDataLines(LinkedList lines, int n){ + private LinkedList generateDataLines(LinkedList lines, int n) { m = 5d; b = 0d; @@ -72,28 +70,26 @@ public class DatasetGenerator extends Observable{ //speichere die Koordinaten in einer HashMap, damit keine Punkte //entstehen deren x-Koordinate zu sehr beieinander liegt. - while (size < n){ + while (size < n) { double y = random.nextGaussian(); double signal = m * y + b; signal *= -1; - if (!points.containsKey(y)){ - points.put(y,signal); + if (!points.containsKey(y)) { + points.put(y, signal); size++; } } int idx = lines.size(); - for (Double d :points.keySet()) { + for (Double d : points.keySet()) { Line line = new Line((double) d, points.get(d)); - line.setId(idx+""); + line.setId(idx + ""); lines.add(line); idx++; } - String[] ret = {"generator","Es wurden "+100+" Daten generiert mit den Parametern", - "
m = "+m+"", - "
b = "+b+""}; + String[] ret = {"generator", "Es wurden " + 100 + " Daten generiert mit den Parametern"}; setChanged(); notifyObservers(ret); return lines; @@ -106,22 +102,21 @@ public class DatasetGenerator extends Observable{ double from = 0; double to = Math.PI * 5; //obere Grenze für die neuen Punkte - int n = size/2 + lines.size(); + int n = size / 2 + lines.size(); //calculate the distance between every two points double distance = (to - from) / ((double) n); //create points - double currentDistance= from; + double currentDistance = from; //an die aktuelle Liste dranhängen - for(int i=lines.size(); i < n; i++) - { + for (int i = lines.size(); i < n; i++) { double x = Math.cos(currentDistance); double y = Math.sin(currentDistance); - Line line = new Line(x,y); - line.setId(i+""); + Line line = new Line(x, y); + line.setId(i + ""); lines.add(line); //distance for the next iteration @@ -129,7 +124,7 @@ public class DatasetGenerator extends Observable{ } - return generateDataLines(lines,size/2); + return generateDataLines(lines, size / 2); } } diff --git a/src/main/java/Presenter/ImportExport/DataExporter.java b/src/main/java/presenter/io/DataExporter.java similarity index 74% rename from src/main/java/Presenter/ImportExport/DataExporter.java rename to src/main/java/presenter/io/DataExporter.java index 61fa6e6..a2502c1 100644 --- a/src/main/java/Presenter/ImportExport/DataExporter.java +++ b/src/main/java/presenter/io/DataExporter.java @@ -1,7 +1,7 @@ -package Presenter.ImportExport; +package presenter.io; -import Model.Line; -import Model.LineModel; +import model.Line; +import model.LineModel; import com.opencsv.CSVWriter; import java.io.File; @@ -16,24 +16,24 @@ import java.util.Observable; * @Email: a_wolf28@uni-muenster.de * @Date: 03.08.2017. */ -public class DataExporter extends Observable{ +public class DataExporter extends Observable { private LineModel lineModel; private File file; - public DataExporter(LineModel model, File file){ + public DataExporter(LineModel model, File file) { this.file = file; this.lineModel = model; } - public void export(){ + public void export() { CSVWriter writer = null; try { writer = new CSVWriter(new FileWriter(file), ','); // feed in your array (or convert your data to an array) String[] entries = new String[3]; - for (Line line : lineModel.getLines()){ + for (Line line : lineModel.getLines()) { entries[0] = line.getId(); entries[1] = line.getM().toString(); Double tmp = (-1) * line.getB(); @@ -41,7 +41,7 @@ public class DataExporter extends Observable{ writer.writeNext(entries); } writer.close(); - String[] ret = {"export","Das aktuelle Modell wurde erfolgreich unter: "+file.getAbsolutePath()+" gespeichert."}; + String[] ret = {"export", "Das aktuelle Modell wurde erfolgreich unter: " + file.getAbsolutePath() + " gespeichert."}; setChanged(); notifyObservers(ret); } catch (IOException e) { diff --git a/src/main/java/presenter/io/DataImporter.java b/src/main/java/presenter/io/DataImporter.java new file mode 100644 index 0000000..9f55590 --- /dev/null +++ b/src/main/java/presenter/io/DataImporter.java @@ -0,0 +1,77 @@ +package presenter.io; + +import model.Line; +import model.LineModel; +import presenter.Presenter; +import com.opencsv.CSVReader; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.util.List; +import java.util.Observable; + + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 21.06.2017. + */ +public class DataImporter extends Observable { + + private File file; + private CSVReader reader; + private LineModel model; + private Presenter presenter; + + + public DataImporter(File file, Presenter presenter) { + this.model = new LineModel(); + this.presenter = presenter; + this.presenter.setModel(this.model); + //System.out.println(this.model.getLines().size()+ " die Anzahl der aktuellen Lines."); + + + this.file = file; + try { + + this.reader = new CSVReader(new FileReader(file)); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + } + + public void run() { + + try { + List lines = reader.readAll(); + int counter = 0; + String[] result = {"import", lines.size() + "", ""}; + //System.out.println("+-------------------------------------------------------------------------------+"); + for (String[] nextLine : lines) { + // nextLine[] is an array of values from the line + Double x = Double.parseDouble(nextLine[1]); + Double y = Double.parseDouble(nextLine[2]) * (-1); + Line line = new Line(x, y); + line.setId(counter + ""); + this.presenter.getModel().addLine(line); + //System.out.format("|\t\t\t\t\t %-11d \t|\t\t\t\t\t %-11f \t|\t\t\t\t\t %-11f \t\t\t\t\t|\n", id,x,y); + setChanged(); + counter++; + result[2] = counter + ""; + Thread.sleep(10); + notifyObservers(result); + } + + //System.out.println("+-------------------------------------------------------------------------------+"); + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/main/java/presenter/io/EvalResultLatexExport.java b/src/main/java/presenter/io/EvalResultLatexExport.java new file mode 100644 index 0000000..6f54be7 --- /dev/null +++ b/src/main/java/presenter/io/EvalResultLatexExport.java @@ -0,0 +1,96 @@ +package presenter.io; + +import javax.swing.*; +import javax.swing.table.DefaultTableModel; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 08.09.2017. + */ +public class EvalResultLatexExport { + + private DefaultTableModel model; + private File file; + + public EvalResultLatexExport(DefaultTableModel model, File file) { + this.model = model; + this.file = file; + } + + /** + * e.g. Source: https://en.wikibooks.org/wiki/LaTeX/Tables + * \begin{tabular}{l*{3}{c}} + * Team & P & W & D & L & F & A & Pts \\\hline + * Manchester United & 6 & 4 & 0 & 2 & 10 & 5 & 12 \\ + * Celtic & 6 & 3 & 0 & 3 & 8 & 9 & 9 \\ + * Benfica & 6 & 2 & 1 & 3 & 7 & 8 & 7 \\ + * FC Copenhagen & 6 & 2 & 1 & 3 & 5 & 8 & 7 \\ + * \end{tabular} + * + * @return + */ + private String createOutputData() { + String split = "&"; + StringBuilder doc = new StringBuilder(); + doc.append("\\begin{tabular}{l|*{3}{r}}" + "\r\n"); + for (int i = 0; i < model.getColumnCount(); i++) { + if (model.getValueAt(0, i).toString() != "" || model.getRowCount() > 5) + doc.append("\\textsc{" + model.getColumnName(i) + "}" + split); + } + + doc.deleteCharAt(doc.lastIndexOf(split)); + doc.append("\\\\\\hline\\hline" + "\r\n"); + + for (int i = 0; i < model.getRowCount() - 1; i++) { + for (int j = 0; j < model.getColumnCount(); j++) { + if (model.getValueAt(i, j).toString() != "") { + if (j == 0) { + doc.append("\\textbf{" + model.getValueAt(i, j).toString() + "}" + split); + } else { + Double val = Double.parseDouble((String) model.getValueAt(i, j)); + doc.append(String.format("%.3f", val) + split); + } + } + } + if (model.getValueAt(i, 0) != "") { + doc.deleteCharAt(doc.lastIndexOf(split)); + } + doc.append("\\\\" + "\r\n"); + } + doc.append("\\end{tabular}"); + return doc.toString(); + } + + public void writeFile() { + FileWriter fileWriter = null; + BufferedWriter bufferedWriter = null; + try { + fileWriter = new FileWriter(file); + bufferedWriter = new BufferedWriter(fileWriter); + bufferedWriter.write(createOutputData()); + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(null, "Export war Erfolgreich!"); + }); + + + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + bufferedWriter.close(); + fileWriter.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + } + +} diff --git a/src/main/java/view/MainFrame.java b/src/main/java/view/MainFrame.java new file mode 100644 index 0000000..2fc754c --- /dev/null +++ b/src/main/java/view/MainFrame.java @@ -0,0 +1,547 @@ +package view; + + +import model.Line; +import presenter.AbstractPresenter; +import presenter.Presenter; +import view.listener.*; +import view.panels.*; +import view.panels.tabs.LMSPanel; +import view.panels.tabs.RMPanel; +import view.panels.tabs.TSPanel; +import view.panels.tabs.TabPanel; + +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.*; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +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 MainFrame extends JFrame { + + private AbstractPresenter presenter; + private Boolean lmsIsComplete = false; + private Boolean rmIsComplete = false; + private Boolean tsIsComplete = false; + + private JButton arrangementButton; + private JButton importButton; + private JButton generateButton; + private JButton exportButton; + + private InfoPanel output; + private MenuBar menu; + private JToolBar toolBar; + private TabPanel lmsPanel; + private TabPanel rmPanel; + private TabPanel tsPanel; + + private DualityPanel arrangement; + private JDialog arrangementDialog; + private PlotPanel plotLMS; + private PlotPanel plotRM; + private PlotPanel plotTS; + private JDialog progressDialog; + private JDialog evaluationDialog; + + private Container progressContent; + private JProgressBar progressBar; + + + private JSplitPane splitpane; + private JScrollPane scrollPane; + private JTabbedPane tabbedPane; + private EvaluationPanel evaluationPanel; + + public MainFrame() { + super(); + initializeComponents(); + setDimensions(); + setLayouts(); + setTitles(); + + addComponents(); + + setCloseOperations(); + setIcons(); + disableFunctionality(); + this.setVisible(true); + } + + + /******************************************************************************************************************* + * visualisierungs methoden + ******************************************************************************************************************/ + + public void createDualityDialog() { + arrangement = new DualityPanel(); + arrangementDialog = new JDialog(); + arrangementDialog.setTitle("Dualraum - Dialog"); + arrangementDialog.setMinimumSize(new Dimension(1024, 768)); + arrangementDialog.setPreferredSize(new Dimension(800, 800)); + arrangementDialog.setLocationRelativeTo(this); + arrangementDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); + arrangementButton.addActionListener(new DualityVisualizerListener((Presenter) getPresenter())); + arrangement.clear(); + arrangement.setPrameters(getPresenter().getModel().getLines(), + getPresenter().getModel().getNodes(), + getPresenter().getModel().getxMinimum(), + getPresenter().getModel().getxMaximum(), + getPresenter().getModel().getyMinimum(), + getPresenter().getModel().getyMaximum()); + arrangement.createArrangement(); + + SwingUtilities.invokeLater(() -> { + arrangementDialog.add(arrangement); + arrangementDialog.setLocationRelativeTo(this); + arrangementDialog.revalidate(); + arrangementDialog.repaint(); + arrangementDialog.setVisible(true); + }); + } + + public void visualizeLMS(double m, double b) { + plotLMS = new PlotPanel(); + lmsPanel.setPlotPanel(plotLMS); + createPlot(m, b, plotLMS, lmsPanel, "LMS"); + } + + public void visualizeRM(double m, double b) { + plotRM = new PlotPanel(); + rmPanel.setPlotPanel(plotRM); + createPlot(m, b, plotRM, rmPanel, "RM"); + } + + public void visualizeTS(double m, double b) { + plotTS = new PlotPanel(); + tsPanel.setPlotPanel(plotTS); + createPlot(m, b, plotTS, tsPanel, "TS"); + } + + public void createPlot(double m, double b, PlotPanel plot, JPanel panel, String name) { + SwingUtilities.invokeLater(() -> { + plot.clear(); + plot.createPlot(getPresenter().getModel().getLines()); + plot.addLineToPlot(m, b, name); + panel.revalidate(); + }); + } + + public void showImportProgress(Integer progress) { + progressBar.setValue(progress); + progressBar.setStringPainted(true); + progressDialog.setVisible(true); + } + + public void showEvauluationDialog() { + if (evaluationDialog == null) { + SwingUtilities.invokeLater(() -> { + evaluationDialog = new JDialog(); + evaluationDialog.setTitle("evaluation"); + evaluationDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); + evaluationDialog.setSize(new Dimension(1800, 800)); + evaluationDialog.setLocationRelativeTo(null); + + evaluationPanel = new EvaluationPanel(this); + evaluationDialog.setLocationRelativeTo(this); + evaluationDialog.add(evaluationPanel); + evaluationDialog.setVisible(true); + }); + } else { + SwingUtilities.invokeLater(() -> { + evaluationDialog.setLocationRelativeTo(this); + evaluationDialog.setVisible(true); + }); + } + + } + + public void appendEvalResult(Object[] res, int col, boolean isApprCol) { + SwingUtilities.invokeLater(() -> { + Object[] tmp = Arrays.asList(res).subList(2, res.length).toArray(); + if (isApprCol) { + evaluationPanel.setCurrentRow(tmp.length); + evaluationPanel.addColumn(tmp, col, true); + } else { + evaluationPanel.addColumn(tmp, col + 1, false); + } + evaluationPanel.repaint(); + evaluationPanel.revalidate(); + }); + } + + public void appendEvalResult(Object[] res) { + SwingUtilities.invokeLater(() -> { + Object[] tmp = Arrays.asList(res).subList(1, res.length).toArray(); + evaluationPanel.addRow(tmp); + evaluationPanel.repaint(); + evaluationPanel.revalidate(); + }); + } + + public void drawLineResult(Object[] res, int alg) { + SwingUtilities.invokeLater(() -> { + Object[] result = Arrays.asList(res).subList(2, res.length).toArray(); + evaluationPanel.drawLines(result, alg); + evaluationPanel.repaint(); + evaluationPanel.revalidate(); + }); + } + + public void drawLineResults(Object[] res) { + SwingUtilities.invokeLater(() -> { + Object[] result = Arrays.asList(res).subList(1, res.length).toArray(); + ArrayList algs = new ArrayList<>(); + + for (int i = 0; i < (result.length + 1) / 3; i++) { + String name = (String) result[(3 * i)]; + String m = (String) result[(3 * i) + 1]; + String b = (String) result[(3 * i) + 2]; + Double[] tmp = {Double.parseDouble(name), Double.parseDouble(m), Double.parseDouble(b)}; + algs.add(tmp); + } + + evaluationPanel.drawLines(algs); + evaluationPanel.repaint(); + evaluationPanel.revalidate(); + }); + } + + public void addEvalDataset(LinkedList lines) { + SwingUtilities.invokeLater(() -> { + evaluationPanel.setDualPoints(lines); + evaluationPanel.repaint(); + evaluationPanel.revalidate(); + }); + } + + + /******************************************************************************************************************* + * init GUI + ******************************************************************************************************************/ + private void setTitles() { + this.setTitle("Algorithmen zur Berechnung von Ausgleichgeraden"); + importButton.setText("Import"); + exportButton.setText("Export"); + generateButton.setText("Generiere"); + arrangementButton.setText("Dualraum"); + } + + private void setupTabbedPane() { + tabbedPane.add("Least Median of Squares", lmsPanel); + tabbedPane.add("Repeated Median", rmPanel); + tabbedPane.add("Theil-Sen", tsPanel); + } + + private void addComponents() { + toolBar.add(arrangementButton); + toolBar.add(importButton); + toolBar.add(exportButton); + toolBar.add(generateButton); + toolBar.setFloatable(false); + + setJMenuBar(menu.getMenuBar()); + add(toolBar); + //northPanel.add(toolBar); + + setupSplitPane(); + setupTabbedPane(); + + progressContent.add(progressBar, BorderLayout.CENTER); + progressBar.setBorder(BorderFactory.createTitledBorder("Import...")); + progressDialog.setLocationRelativeTo(null); + ((JPanel) progressDialog.getContentPane()).setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY)); + + this.add(toolBar, BorderLayout.NORTH); + this.add(splitpane, BorderLayout.CENTER); + + } + + private void setupSplitPane() { + splitpane.setOrientation(JSplitPane.HORIZONTAL_SPLIT); + splitpane.setResizeWeight(.5d); + splitpane.setContinuousLayout(true); + splitpane.setLeftComponent(output); + splitpane.setRightComponent(tabbedPane); + } + + private void setCloseOperations() { + this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + progressDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); + } + + private void setDimensions() { + this.setExtendedState(JFrame.MAXIMIZED_BOTH); + this.setMinimumSize(new Dimension(1024,768)); + this.setResizable(true); + GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); + this.setMaximizedBounds(env.getMaximumWindowBounds()); + lmsPanel.setMinimumSize(new Dimension(400, 500)); + rmPanel.setMinimumSize(new Dimension(400, 500)); + tsPanel.setMinimumSize(new Dimension(400, 500)); + output.setMinimumSize(new Dimension(400, 500)); + progressDialog.setSize(300, 45); + progressDialog.setResizable(false); + progressDialog.setUndecorated(true); + } + + private void setLayouts() { + this.setLayout(new BorderLayout()); + toolBar.setLayout(new FlowLayout(FlowLayout.LEFT)); + } + + private void initializeComponents() { + //panels + toolBar = new JToolBar(); + lmsPanel = new LMSPanel(); + rmPanel = new RMPanel(); + tsPanel = new TSPanel(); + menu = new MenuBar(this); + + //Dialogs + progressDialog = new JDialog(); + progressDialog.setLocationRelativeTo(null); + progressContent = progressDialog.getContentPane(); + progressBar = new JProgressBar(); + + //Panes + tabbedPane = new JTabbedPane(); + output = new InfoPanel(); + splitpane = new JSplitPane(); + + //Buttons + arrangementButton = new JButton(); + importButton = new JButton(); + generateButton = new JButton(); + exportButton = new JButton(); + } + + private void setIcons() { + try { + ClassLoader classLoader = getClass().getClassLoader(); + Image imgImport = ImageIO.read(classLoader.getResource("import.png")).getScaledInstance(16, 16, Image.SCALE_SMOOTH); + Image imgPlot = ImageIO.read(classLoader.getResource("plot.png")).getScaledInstance(16, 16, Image.SCALE_SMOOTH); + Image imgStart = ImageIO.read(classLoader.getResource("start.png")).getScaledInstance(32, 32, Image.SCALE_SMOOTH); + Image imgGenerate = ImageIO.read(classLoader.getResource("generate.png")).getScaledInstance(16, 16, Image.SCALE_SMOOTH); + Image imgExport = ImageIO.read(classLoader.getResource("export.png")).getScaledInstance(16, 16, Image.SCALE_SMOOTH); + Image imgFrame = ImageIO.read(classLoader.getResource("frame.png")).getScaledInstance(32, 23, Image.SCALE_SMOOTH); + + + importButton.setIcon(new ImageIcon(imgImport)); + exportButton.setIcon(new ImageIcon(imgExport)); + generateButton.setIcon(new ImageIcon(imgGenerate)); + arrangementButton.setIcon(new ImageIcon(imgPlot)); + lmsPanel.getStartButton().setIcon(new ImageIcon(imgStart)); + rmPanel.getStartButton().setIcon(new ImageIcon(imgStart)); + tsPanel.getStartButton().setIcon(new ImageIcon(imgStart)); + this.setIconImage(imgFrame); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void setActionListeners() { + + //action listener für MenuItems + menu.addActionListeners(); + + //action listener für diese Klasse + arrangementButton.addActionListener(new DualityVisualizerListener((Presenter) getPresenter())); + lmsPanel.getStartButton().addActionListener(new StartAlgorithmListener(((Presenter) getPresenter()), lmsPanel)); + rmPanel.getStartButton().addActionListener(new StartAlgorithmListener(((Presenter) getPresenter()), rmPanel)); + tsPanel.getStartButton().addActionListener(new StartAlgorithmListener(((Presenter) getPresenter()), tsPanel)); + importButton.addActionListener(new ImportDataListener((Presenter) this.getPresenter() , this)); + exportButton.addActionListener(new ExportDataListener((Presenter) this.getPresenter() , this)); + generateButton.addActionListener(new GenerateDataListener((Presenter) this.getPresenter())); + + } + + public void enableFunctionality() { + this.getLmsPanel().getStartButton().setEnabled(true); + this.getRmPanel().getStartButton().setEnabled(true); + this.getTsPanel().getStartButton().setEnabled(true); + this.getArrangementButton().setEnabled(true); + this.getExportButton().setEnabled(true); + } + + public void disableFunctionality() { + this.getLmsPanel().getStartButton().setEnabled(false); + this.getRmPanel().getStartButton().setEnabled(false); + this.getTsPanel().getStartButton().setEnabled(false); + this.getArrangementButton().setEnabled(false); + this.getExportButton().setEnabled(false); + } + + /******************************************************************************************************************* + * log Methode + ******************************************************************************************************************/ + public void log(String s) { + SwingUtilities.invokeLater(() -> output.appendParagraph(s)); + } + + public void logError(String s) { + SwingUtilities.invokeLater(() -> output.appendParagraphRed(s)); + } + + public void logSuccess(String s) { + SwingUtilities.invokeLater(() -> output.appendParagraphGreen(s)); + } + + public void logHeading(String s) { + SwingUtilities.invokeLater(() -> output.appendParagraphWithHeading(s)); + } + + public void createTable(List heading, List> rows) { + SwingUtilities.invokeLater(() -> output.logTable(heading, rows)); + } + + /******************************************************************************************************************* + * Getter und Setter Methoden + ******************************************************************************************************************/ + + public Boolean getLmsIsComplete() { + return lmsIsComplete; + } + + public void setLmsIsComplete(Boolean lmsIsComplete) { + this.lmsIsComplete = lmsIsComplete; + } + + public Boolean getRmIsComplete() { + return rmIsComplete; + } + + public void setRmIsComplete(Boolean rmIsComplete) { + this.rmIsComplete = rmIsComplete; + } + + public Boolean getTsIsComplete() { + return tsIsComplete; + } + + public void setTsIsComplete(Boolean tsIsComplete) { + this.tsIsComplete = tsIsComplete; + } + + public JButton getArrangementButton() { + return arrangementButton; + } + + public void setArrangementButton(JButton arrangementButton) { + this.arrangementButton = arrangementButton; + } + + public JButton getImportButton() { + return importButton; + } + + public void setImportButton(JButton importButton) { + this.importButton = importButton; + } + + public JToolBar getToolBar() { + return toolBar; + } + + public void setToolBar(JToolBar toolBar) { + this.toolBar = toolBar; + } + + public JDialog getArrangementDialog() { + return arrangementDialog; + } + + public void setArrangementDialog(JDialog arrangementDialog) { + this.arrangementDialog = arrangementDialog; + } + + public InfoPanel getOutput() { + return output; + } + + public void setOutput(InfoPanel output) { + this.output = output; + } + + public MenuBar getMenu() { + return menu; + } + + public TabPanel getLmsPanel() { + return lmsPanel; + } + + public JSplitPane getSplitpane() { + return splitpane; + } + + public void setSplitpane(JSplitPane splitpane) { + this.splitpane = splitpane; + } + + public JScrollPane getScrollPane() { + return scrollPane; + } + + public void setScrollPane(JScrollPane scrollPane) { + this.scrollPane = scrollPane; + } + + public TabPanel getRmPanel() { + return rmPanel; + } + + public void setRmPanel(TabPanel rmPanel) { + this.rmPanel = rmPanel; + } + + public PlotPanel getPlotLMS() { + return plotLMS; + } + + public void setPlotLMS(PlotPanel plotLMS) { + this.plotLMS = plotLMS; + } + + public AbstractPresenter getPresenter() { + return presenter; + } + + public void setPresenter(AbstractPresenter presenter) { + this.presenter = presenter; + } + + public JDialog getProgressDialog() { + return progressDialog; + } + + public void setProgressDialog(JDialog progressDialog) { + this.progressDialog = progressDialog; + } + + public TabPanel getTsPanel() { + return tsPanel; + } + + public void setTsPanel(TabPanel tsPanel) { + this.tsPanel = tsPanel; + } + + public JButton getExportButton() { + return exportButton; + } + + public void setExportButton(JButton exportButton) { + this.exportButton = exportButton; + } +} diff --git a/src/main/java/view/MenuBar.java b/src/main/java/view/MenuBar.java new file mode 100644 index 0000000..3e1947b --- /dev/null +++ b/src/main/java/view/MenuBar.java @@ -0,0 +1,87 @@ +package view; + +import presenter.Presenter; +import view.MainFrame; +import view.listener.ExportDataListener; +import view.listener.GenerateDataListener; +import view.listener.ImportDataListener; +import view.panels.AboutPanel; + +import javax.swing.*; +import java.awt.*; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 29.05.2017. + */ +public class MenuBar { + + private MainFrame view; + + private JMenuBar menuBar; + private JMenu fileMenu; + private JMenu toolsMenu; + private JMenu aboutMenu; + + private JMenuItem exitItem; + private JMenuItem importItem; + private JMenuItem exportItem; + private JMenuItem generateItem; + private JMenuItem evaluateItem; + private JMenuItem aboutItem; + + public MenuBar(MainFrame view) { + this.menuBar = new JMenuBar(); + this.view = view; + this.fileMenu = new JMenu("Datei"); + this.toolsMenu = new JMenu("Extras"); + this.aboutMenu = new JMenu("Info"); + + + this.exitItem = new JMenuItem("Exit"); + this.importItem = new JMenuItem("Import"); + this.exportItem = new JMenuItem("Export"); + this.generateItem = new JMenuItem("Generiere..."); + this.aboutItem = new JMenuItem("Über das Programm"); + + this.evaluateItem = new JMenuItem("Evaluation"); + + + fileMenu.add(exitItem); + fileMenu.add(importItem); + fileMenu.add(exportItem); + + toolsMenu.add(generateItem); + toolsMenu.add(evaluateItem); + + aboutMenu.add(aboutItem); + + menuBar.add(fileMenu); + menuBar.add(toolsMenu); + menuBar.add(aboutMenu); + } + + public void addActionListeners(){ + this.exitItem.addActionListener(e -> {System.exit(0);}); + this.evaluateItem.addActionListener(e -> {view.showEvauluationDialog();}); + this.importItem.addActionListener(new ImportDataListener((Presenter) view.getPresenter(), view)); + this.exportItem.addActionListener(new ExportDataListener((Presenter) view.getPresenter(), view)); + this.generateItem.addActionListener(new GenerateDataListener((Presenter) view.getPresenter())); + this.aboutItem.addActionListener(e -> { + SwingUtilities.invokeLater(() -> { + JDialog dialog = new JDialog(); + dialog.setSize(410,420); + dialog.setResizable(false); + dialog.add(new AboutPanel()); + dialog.setVisible(true); + }); + }); + } + + public JMenuBar getMenuBar() { + return menuBar; + } +} diff --git a/src/main/java/view/custom/ButtonGroupAtLeastTwo.java b/src/main/java/view/custom/ButtonGroupAtLeastTwo.java new file mode 100644 index 0000000..8dd6c82 --- /dev/null +++ b/src/main/java/view/custom/ButtonGroupAtLeastTwo.java @@ -0,0 +1,76 @@ +package view.custom; + +import javax.swing.*; +import java.util.HashSet; +import java.util.Set; + +/** + * Source: https://stackoverflow.com/questions/14892515/how-to-enforce-at-least-one-checkbox-in-a-group-is-selected + *

+ * A ButtonGroup for check-boxes enforcing that at least two remains selected. + *

+ * When the group has exactly two buttons, deselecting the last selected one + * automatically selects the other. + *

+ * When the group has more buttons, deselection of the last selected one is denied. + */ +public class ButtonGroupAtLeastTwo extends ButtonGroup { + + private final Set selected = new HashSet<>(); + + @Override + public void setSelected(ButtonModel model, boolean b) { + if (b && !this.selected.contains(model)) { + select(model, true); + } else if (!b && this.selected.contains(model)) { + if (this.buttons.size() == 3 && this.selected.size() == 2) { + select(model, false); + + AbstractButton otherOne = this.buttons.get(0).getModel() == model ? + this.buttons.get(1) : this.buttons.get(0); + + AbstractButton otherTwo = this.buttons.get(1).getModel() == model ? + this.buttons.get(2) : this.buttons.get(1); + + AbstractButton otherThree = this.buttons.get(2).getModel() == model ? + this.buttons.get(1) : this.buttons.get(2); + + + select(otherOne.getModel(), true); + select(otherTwo.getModel(), true); + select(otherThree.getModel(), true); + } else if (this.selected.size() > 2) { + this.selected.remove(model); + model.setSelected(false); + } + } + } + + private void select(ButtonModel model, boolean b) { + if (b) { + this.selected.add(model); + } else { + this.selected.remove(model); + } + model.setSelected(b); + } + + @Override + public boolean isSelected(ButtonModel m) { + return this.selected.contains(m); + } + + public void addAll(AbstractButton... buttons) { + for (AbstractButton button : buttons) { + add(button); + } + } + + @Override + public void add(AbstractButton button) { + if (button.isSelected()) { + this.selected.add(button.getModel()); + } + super.add(button); + } +} \ No newline at end of file diff --git a/src/main/java/view/custom/ColorColumnRenderer.java b/src/main/java/view/custom/ColorColumnRenderer.java new file mode 100644 index 0000000..226149a --- /dev/null +++ b/src/main/java/view/custom/ColorColumnRenderer.java @@ -0,0 +1,35 @@ +package view.custom; + +import javax.swing.*; +import javax.swing.table.DefaultTableCellRenderer; +import java.awt.*; + +/** + * Source: http://esus.com/creating-a-jtable-with-a-different-background-color-per-column/ + *

+ * Applied background and foreground color to single column of a JTable + * in order to distinguish it apart from other columns. + */ +public class ColorColumnRenderer extends DefaultTableCellRenderer { + + Color bkgndColor, fgndColor; + + public ColorColumnRenderer(Color bkgnd, Color foregnd) { + super(); + bkgndColor = bkgnd; + fgndColor = foregnd; + } + + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, + boolean hasFocus, int row, int column) { + Component cell = super.getTableCellRendererComponent + (table, value, isSelected, hasFocus, row, column); + + cell.setBackground(bkgndColor); + cell.setForeground(fgndColor); + cell.setFont(new Font("SansSerif", Font.BOLD, 12)); + this.setHorizontalAlignment(JLabel.CENTER); + + return cell; + } +} \ No newline at end of file diff --git a/src/main/java/view/listener/DualityVisualizerListener.java b/src/main/java/view/listener/DualityVisualizerListener.java new file mode 100644 index 0000000..8637630 --- /dev/null +++ b/src/main/java/view/listener/DualityVisualizerListener.java @@ -0,0 +1,30 @@ +package view.listener; + +import presenter.Presenter; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 10.09.2017. + */ +public class DualityVisualizerListener implements ActionListener { + + private Presenter presenter; + + public DualityVisualizerListener(Presenter presenter) { + this.presenter = presenter; + } + + @Override + public void actionPerformed(ActionEvent e) { + SwingUtilities.invokeLater(() -> { + presenter.visualizeDualLines(); + }); + } +} diff --git a/src/main/java/view/listener/ExportDataListener.java b/src/main/java/view/listener/ExportDataListener.java new file mode 100644 index 0000000..be2ce72 --- /dev/null +++ b/src/main/java/view/listener/ExportDataListener.java @@ -0,0 +1,52 @@ +package view.listener; + +import presenter.Presenter; + +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.filechooser.FileSystemView; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 10.09.2017. + */ +public class ExportDataListener implements ActionListener { + + private Presenter presenter; + private Container component; + + public ExportDataListener(Presenter presenter, Container component) { + this.presenter = presenter; + this.component = component; + } + + @Override + public void actionPerformed(ActionEvent e) { + SwingUtilities.invokeLater(() -> { + File file = null; + JFileChooser chooser = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory()); + chooser.setPreferredSize(new Dimension(800, 700)); + chooser.setFileFilter(new FileNameExtensionFilter("Comma-Separated Value", "csv", "text")); + chooser.setMultiSelectionEnabled(false); + chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + + + if (chooser.showSaveDialog(component) == JFileChooser.APPROVE_OPTION) { + //System.out.println ("Datei "+chooser.getSelectedFile()+ " ausgewählt."); + file = chooser.getSelectedFile(); + String filename = file.getAbsolutePath().contains(".csv") ? file.getAbsolutePath() : file.getAbsolutePath().concat(".csv"); + File withExtension = new File(filename); + final File input = withExtension; + Thread t = new Thread(() -> presenter.startExport(input)); + t.start(); + } + }); + } +} diff --git a/src/main/java/view/listener/GenerateDataListener.java b/src/main/java/view/listener/GenerateDataListener.java new file mode 100644 index 0000000..72991bc --- /dev/null +++ b/src/main/java/view/listener/GenerateDataListener.java @@ -0,0 +1,30 @@ +package view.listener; + +import presenter.Presenter; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 10.09.2017. + */ +public class GenerateDataListener implements ActionListener { + + private Presenter presenter; + + public GenerateDataListener(Presenter presenter) { + this.presenter = presenter; + } + + @Override + public void actionPerformed(ActionEvent e) { + Thread t = new Thread(() -> presenter.generateDataset()); + t.start(); + } +} \ No newline at end of file diff --git a/src/main/java/view/listener/ImportDataListener.java b/src/main/java/view/listener/ImportDataListener.java new file mode 100644 index 0000000..ed46f9c --- /dev/null +++ b/src/main/java/view/listener/ImportDataListener.java @@ -0,0 +1,51 @@ +package view.listener; + +import presenter.Presenter; + +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.filechooser.FileSystemView; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 10.09.2017. + */ +public class ImportDataListener implements ActionListener { + + private Presenter presenter; + private Container component; + + public ImportDataListener(Presenter presenter, Container component) { + this.presenter = presenter; + this.component = component; + } + + @Override + public void actionPerformed(ActionEvent e) { + SwingUtilities.invokeLater(() -> { + File file = null; + JFileChooser chooser = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory()); + chooser.setPreferredSize(new Dimension(800, 700)); + chooser.setFileFilter(new FileNameExtensionFilter("Comma-Separated Value", "csv", "text")); + + chooser.setMultiSelectionEnabled(false); + chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + + + if (chooser.showOpenDialog(component) == JFileChooser.APPROVE_OPTION) { + //System.out.println ("Datei "+chooser.getSelectedFile()+ " ausgewählt."); + file = chooser.getSelectedFile(); + final File input = file; + Thread t = new Thread(() -> presenter.startImport(input)); + t.start(); + } + }); + } +} diff --git a/src/main/java/view/listener/StartAlgorithmListener.java b/src/main/java/view/listener/StartAlgorithmListener.java new file mode 100644 index 0000000..b9e28e8 --- /dev/null +++ b/src/main/java/view/listener/StartAlgorithmListener.java @@ -0,0 +1,54 @@ +package view.listener; + +import presenter.Presenter; +import presenter.algorithms.Algorithm; +import presenter.algorithms.LeastMedianOfSquaresEstimator; +import view.panels.tabs.LMSPanel; +import view.panels.tabs.RMPanel; +import view.panels.tabs.TSPanel; +import view.panels.tabs.TabPanel; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 10.09.2017. + */ +public class StartAlgorithmListener implements ActionListener { + + private Presenter presenter; + private TabPanel tabPanel; + + public StartAlgorithmListener(Presenter presenter, TabPanel tabPanel) { + this.presenter = presenter; + this.tabPanel = tabPanel; + } + + @Override + public void actionPerformed(ActionEvent e) { + if (tabPanel instanceof LMSPanel){ + if ( ((LMSPanel) tabPanel).getInput() != null) { + Thread t = new Thread( + () -> presenter.calculateLMS(((LMSPanel) tabPanel).getInput())); + t.start(); + } + } else if (tabPanel instanceof RMPanel){ + if ( ((RMPanel) tabPanel).getInput() != null) { + Thread t = new Thread( + () -> presenter.calculateRM(((RMPanel) tabPanel).getInput())); + t.start(); + } + } else if(tabPanel instanceof TSPanel){ + Thread t = new Thread( + () -> presenter.calculateTS("")); + t.start(); + } else { + throw new IllegalArgumentException("Unknown Algortihm representation Panel!"); + } + + } +} diff --git a/src/main/java/view/panels/AboutPanel.java b/src/main/java/view/panels/AboutPanel.java new file mode 100644 index 0000000..c2e3cb9 --- /dev/null +++ b/src/main/java/view/panels/AboutPanel.java @@ -0,0 +1,45 @@ +package view.panels; + +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.*; +import java.io.IOException; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 10.09.2017. + */ +public class AboutPanel extends JPanel { + + private JTextArea textArea; + private JLabel imageContainer; + private JPanel contentPane; + private ImageIcon image; + + public AboutPanel(){ + super(); + this.setSize(new Dimension(410,400)); + this.setLayout(new BorderLayout()); + contentPane = new JPanel(new BorderLayout()); + this.textArea = new JTextArea(); + this.textArea.setEditable(false); + this.textArea.setBackground(new Color(0,0,0,0)); + contentPane.add(this.textArea, BorderLayout.CENTER); + ClassLoader classLoader = getClass().getClassLoader(); + try { + image = new ImageIcon(ImageIO.read(classLoader.getResource("wwu.png")).getScaledInstance(300, 87, Image.SCALE_SMOOTH)); + } catch (IOException e) { + e.printStackTrace(); + } + this.imageContainer = new JLabel(image); + contentPane.add(imageContainer, BorderLayout.NORTH); + this.add(new JPanel(), BorderLayout.NORTH); + this.add(contentPane, BorderLayout.CENTER); + this.setVisible(true); + } + + +} diff --git a/src/main/java/view/panels/DualityPanel.java b/src/main/java/view/panels/DualityPanel.java new file mode 100644 index 0000000..079e510 --- /dev/null +++ b/src/main/java/view/panels/DualityPanel.java @@ -0,0 +1,233 @@ +package view.panels; + +import model.Line; +import 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; + +/** + * 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 LinkedList lines; + private LinkedList 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; + + public DualityPanel() { + super(); + this.setPreferredSize(new Dimension(800, 800)); + this.setMinimumSize(new Dimension(800, 800)); + this.setLayout(new BorderLayout()); + } + + public void setPrameters(LinkedList lines, LinkedList 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; + } + + 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.setText("Um in dem Plot hineinzuzoomen kann das Mausrad verwendett werden. \nUm sich anschließen vertikal bzw. horizontal zu bewegen kann die Kombination (Umschalt/Steuerung)\nund Mausrad verwendett werden."); + Font font = new Font("Serif", Font.ITALIC, 12); + info.setFont(font); + info.setForeground(Color.DARK_GRAY); + info.setEditable(false); + info.setWrapStyleWord(true); + + this.add(info, BorderLayout.SOUTH); + this.add(panel, BorderLayout.CENTER); + } + + 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; + } + } + }); + } + + protected void addZooming(ChartPanel chartPanel) { + + chartPanel.addMouseWheelListener(new MouseWheelListener() { + + public void mouseWheelMoved(MouseWheelEvent e) { + + Double min; + Double max; + Double val = e.getPreciseWheelRotation() * -1; + + if (ctrlPressed == true) { + //System.out.println("CTRL + ZOOM"); + min = range.getLowerBound(); + max = range.getUpperBound(); + DateRange dateRangeX = move(val, min, max); + range.setRange(dateRangeX); + } else if (shiftPressed == true) { + //System.out.println("SHIFT + ZOOM"); + min = domain.getLowerBound(); + max = domain.getUpperBound(); + DateRange dateRangeY = move(val, min, max); + domain.setRange(dateRangeY); + } else { + 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); + } + + } + + 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); + } + + 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); + } + + } + }); + } + + public void clear() { + if (dataset != null) + dataset.removeAllSeries(); + } + +} \ No newline at end of file diff --git a/src/main/java/View/Panels/EvaluationPanel.java b/src/main/java/view/panels/EvaluationPanel.java similarity index 69% rename from src/main/java/View/Panels/EvaluationPanel.java rename to src/main/java/view/panels/EvaluationPanel.java index a242c86..f76ea8c 100644 --- a/src/main/java/View/Panels/EvaluationPanel.java +++ b/src/main/java/view/panels/EvaluationPanel.java @@ -1,31 +1,30 @@ -package View.Panels; +package view.panels; -import Model.Line; -import View.MainFrame; +import model.Line; +import presenter.Presenter; +import view.MainFrame; +import view.custom.ButtonGroupAtLeastTwo; +import view.custom.ColorColumnRenderer; -import View.PlotDialog; -import View.custom.ButtonGroupAtLeastOne; +import javax.swing.*; +import javax.swing.border.TitledBorder; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.filechooser.FileSystemView; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.JTableHeader; +import javax.swing.table.TableColumn; +import java.awt.*; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; -import javax.swing.*; -import javax.swing.border.LineBorder; -import javax.swing.border.TitledBorder; -import javax.swing.filechooser.FileNameExtensionFilter; -import javax.swing.table.DefaultTableModel; -import java.awt.*; -import javax.swing.table.JTableHeader; -import javax.swing.table.TableCellRenderer; -import javax.swing.table.TableColumn; -import javax.swing.table.TableColumnModel; -import View.custom.ColorColumnRenderer; + /** * Created by * Armin Wolf * on 02.08.17. */ -public class EvaluationPanel extends JPanel{ +public class EvaluationPanel extends JPanel { private final MainFrame view; private JTable table; @@ -38,11 +37,11 @@ public class EvaluationPanel extends JPanel{ private JRadioButton evalTypeTwo; //N: Alg - 1: Data private ButtonGroup radiobuttonGroup; private ButtonGroup checkboxGroup; - private ButtonGroupAtLeastOne checkboxAtLeastOne; + private ButtonGroupAtLeastTwo checkboxAtLeastOne; - private JCheckBox lms; //1: Alg - N: Data - private JCheckBox rm; //N: Alg - 1: Data - private JCheckBox ts; //1: Alg - N: Data + private JCheckBox lms; //1: Alg - N: Data + private JCheckBox rm; //N: Alg - 1: Data + private JCheckBox ts; //1: Alg - N: Data private JPanel comp; private JPanel algorithmPanel; @@ -57,10 +56,10 @@ public class EvaluationPanel extends JPanel{ private DefaultTableModel model; private int currentRowOfTypes; private JPanel buttonPanel; - private PlotDialog plotDialog; - private String[] selections = { "Approximationsgüte","Least Median of Squares","Repeated-Median","Theil-Sen"}; + private PlotPanel plotPanel; + private String[] selections = {"Approximationsgüte", "Least Median of Squares", "Repeated-Median", "Theil-Sen"}; - public EvaluationPanel(MainFrame view){ + public EvaluationPanel(MainFrame view) { super(); this.view = view; this.setLayout(new BorderLayout()); @@ -72,9 +71,9 @@ public class EvaluationPanel extends JPanel{ } - private void init(){ - datasetCountLabel = new JLabel("Größe des Datensatzes"); - Integer[] choice = {50,100,200,500,1000,1500}; + private void init() { + datasetCountLabel = new JLabel("Größe des Datensatzes"); + Integer[] choice = {50, 100, 200, 500, 1000, 1500}; datasetCountChoice = new JComboBox(choice); String[] datatypes = {"Punktwolke", "Gerade", "Kreis und Gerade"}; datasetType = new JComboBox<>(datatypes); @@ -88,17 +87,17 @@ public class EvaluationPanel extends JPanel{ exportData.setEnabled(false); evalTypeOne = new JRadioButton("Algorithmus evaluieren"); evalTypeTwo = new JRadioButton("Algorithmen vergleichen"); - lms = new JCheckBox ("Least Median of Squares"); - rm = new JCheckBox ("Repeated Median"); - ts = new JCheckBox ("Theil-Sen"); + lms = new JCheckBox("Least Median of Squares"); + rm = new JCheckBox("Repeated Median"); + ts = new JCheckBox("Theil-Sen"); radiobuttonGroup = new ButtonGroup(); checkboxGroup = new ButtonGroup(); - checkboxAtLeastOne = new ButtonGroupAtLeastOne(); + checkboxAtLeastOne = new ButtonGroupAtLeastTwo(); buttonPanel = new JPanel(new FlowLayout()); leftSidePanel = new JPanel(new BorderLayout()); - comp = new JPanel(new GridLayout(0,1)); - plotDialog = new PlotDialog(); - model = new DefaultTableModel(){ + comp = new JPanel(new GridLayout(0, 1)); + plotPanel = new PlotPanel(); + model = new DefaultTableModel() { @Override public boolean isCellEditable(int row, int column) { //all cells false @@ -117,7 +116,7 @@ public class EvaluationPanel extends JPanel{ } - private void addComponents(){ + private void addComponents() { evalTypeOne.setSelected(true); lms.setSelected(true); checkboxGroup.add(lms); @@ -159,8 +158,8 @@ public class EvaluationPanel extends JPanel{ //Plot - plotDialog.createPlot(new LinkedList<>()); - plotDialog.setBorder(new TitledBorder("Plot")); + plotPanel.createPlot(new LinkedList<>()); + plotPanel.setBorder(new TitledBorder("Plot")); leftSidePanel.add(comp, BorderLayout.NORTH); leftSidePanel.add(scrollPane, BorderLayout.CENTER); @@ -170,7 +169,7 @@ public class EvaluationPanel extends JPanel{ splitPane.setResizeWeight(.5d); splitPane.setContinuousLayout(true); splitPane.setLeftComponent(leftSidePanel); - splitPane.setRightComponent(plotDialog); + splitPane.setRightComponent(plotPanel); this.add(splitPane, BorderLayout.CENTER); @@ -180,12 +179,12 @@ public class EvaluationPanel extends JPanel{ tm.setCellRenderer(new ColorColumnRenderer(Color.lightGray, Color.blue)); } - private void addListener(){ + private void addListener() { start.addActionListener(e -> { int type; int alg; int n; - if (radiobuttonGroup.isSelected(evalTypeOne.getModel())){ + if (radiobuttonGroup.isSelected(evalTypeOne.getModel())) { type = 0; } else { type = 1; @@ -193,7 +192,7 @@ public class EvaluationPanel extends JPanel{ alg = checkSelection(); n = (Integer) datasetCountChoice.getSelectedItem(); String datatyp = (String) datasetType.getSelectedItem(); - view.getPresenter().startEvaluation(type,n,alg,datatyp); + ((Presenter) view.getPresenter()).startEvaluation(type, n, alg, datatyp); clearTable.setEnabled(true); latexExport.setEnabled(true); exportData.setEnabled(true); @@ -215,7 +214,7 @@ public class EvaluationPanel extends JPanel{ checkboxGroup.remove(rm); checkboxGroup.remove(ts); - checkboxAtLeastOne.addAll(lms,rm,ts); + checkboxAtLeastOne.addAll(lms, rm, ts); lms.setSelected(true); rm.setSelected(true); @@ -224,30 +223,28 @@ public class EvaluationPanel extends JPanel{ latexExport.addActionListener(e -> { SwingUtilities.invokeLater(() -> { File file = null; - JFileChooser chooser = new JFileChooser(); - chooser.setPreferredSize(new Dimension(800,700)); - File workingDirectory = new File(System.getProperty("user.dir")); - chooser.setCurrentDirectory(workingDirectory); + JFileChooser chooser = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory()); + chooser.setPreferredSize(new Dimension(800, 700)); chooser.setFileFilter(new FileNameExtensionFilter("LaTeX-Datei", "tex", "text")); chooser.setMultiSelectionEnabled(false); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); - if (chooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION){ + if (chooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) { //System.out.println ("Datei "+chooser.getSelectedFile()+ " ausgewählt."); file = chooser.getSelectedFile(); String filename = file.getAbsolutePath().contains(".tex") ? file.getAbsolutePath() : file.getAbsolutePath().concat(".tex"); File withExtension = new File(filename); final File input = withExtension; - view.getPresenter().startResultExport(model, input); + ((Presenter) view.getPresenter()).startResultExport(model, input); } }); }); clearTable.addActionListener(e -> { - SwingUtilities.invokeLater(() ->{ + SwingUtilities.invokeLater(() -> { int n = model.getDataVector().size(); - for (int i=0;i { SwingUtilities.invokeLater(() -> { - JOptionPane.showMessageDialog(null, "Boooooooooooooooooooooooooooooooooooooooooooooooooooooo! :)"); + JOptionPane.showMessageDialog(this, "Boooooooooooooooooooooooooooooooooooooooooooooooooooooo! :)"); }); }); } - public void addColumn(Object[] data, int col, boolean b){ - if (b){ + public void addColumn(Object[] data, int col, boolean b) { + if (b) { addBlankRows(data.length); } - for (int i=0;i alg){ + public void drawLines(ArrayList alg) { Paint[] color = {Color.ORANGE, Color.RED, Color.MAGENTA}; - String[] name = {"LMS","RM", "TS"}; + String[] name = {"LMS", "RM", "TS"}; - for (Double[] o : alg){ - Double m = o[1]; - Double b = o[1]; - int i = o[0].intValue(); - plotDialog.addLineToPlot(m,b,color[i],name[i]); + for (Double[] o : alg) { + Double m = o[1]; + Double b = o[1]; + int i = o[0].intValue(); + plotPanel.addLineToPlot(m, b, color[i], name[i]); } } - public void drawLines(Object[] results, int alg){ - String[] castedResults = Arrays.copyOf(results, results.length, String[].class); + public void drawLines(Object[] results, int alg) { + String[] castedResults = Arrays.copyOf(results, results.length, String[].class); Paint[] color = {Color.ORANGE, Color.RED, Color.MAGENTA}; - String[] name = {"LMS","RM", "TS"}; + String[] name = {"LMS", "RM", "TS"}; - Double m = Double.parseDouble(castedResults[0]); - Double b = Double.parseDouble(castedResults[1]); - plotDialog.addLineToPlot(m,b,color[alg],name[alg]); + Double m = Double.parseDouble(castedResults[0]); + Double b = Double.parseDouble(castedResults[1]); + plotPanel.addLineToPlot(m, b, color[alg], name[alg]); } - public void setDualPoints(LinkedList points){ - plotDialog = new PlotDialog(); - plotDialog.setBorder(new TitledBorder("Plot")); - splitPane.setRightComponent(plotDialog); - plotDialog.createPlot(points); - plotDialog.repaint(); - plotDialog.revalidate(); + public void setDualPoints(LinkedList points) { + plotPanel = new PlotPanel(); + plotPanel.setBorder(new TitledBorder("Plot")); + splitPane.setRightComponent(plotPanel); + plotPanel.createPlot(points); + plotPanel.repaint(); + plotPanel.revalidate(); } - private void addBlankRows(int n){ - for (int i=0;i" + p + "

"); + + output.setText(content.toString()); + } + + public void appendParagraphWithHeading(String h1) { + + content.append("

" + h1 + "

"); + + output.setText(content.toString()); + } + + public void appendParagraphRed(String p) { + + content.append("

" + p + "

"); + + output.setText(content.toString()); + } + + public void appendParagraphGreen(String p) { + + content.append("

" + p + "

"); + + output.setText(content.toString()); + } + + public void logTable(List heading, List> rows) { + content.append("
"); + content.append(""); + content.append(""); + if (heading.size() > 1) { + for (String str : heading) { + content.append(""); + } + } else { + content.append(""); + } + + content.append(""); + for (List row : rows) { + content.append(""); + for (String entry : row) { + content.append(""); + } + content.append(""); + } + content.append("
" + str + "" + heading.get(0) + "
" + entry + "
"); + content.append("
"); + output.setText(content.toString()); + } + + +} diff --git a/src/main/java/view/panels/PlotPanel.java b/src/main/java/view/panels/PlotPanel.java new file mode 100644 index 0000000..9c0aa8d --- /dev/null +++ b/src/main/java/view/panels/PlotPanel.java @@ -0,0 +1,142 @@ +package view.panels; + +import model.Line; +import org.jfree.chart.ChartFactory; +import org.jfree.chart.ChartPanel; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.plot.PlotOrientation; +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.util.ShapeUtilities; + +import javax.swing.*; +import java.awt.*; +import java.util.ArrayList; +import java.util.LinkedList; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 29.05.2017. + */ +public class PlotPanel extends JPanel { + + private JFreeChart chart; + private ChartPanel panel; + private XYSeriesCollection datapoints; + private XYSeries series; + private Double min; + private Double max; + private XYPlot xyPlot; + private int seriesCount; + + private XYLineAndShapeRenderer renderer; + private Shape diamond; + + public PlotPanel() { + super(); + this.setLayout(new BorderLayout()); + seriesCount = 1; + } + + public void createPlot(LinkedList points) { + if (!points.isEmpty()) { + try { + Thread thread = new Thread(() -> convertData(points)); + thread.start(); + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + //createScatterPlot + chart = ChartFactory.createXYLineChart("", + "X", "Y", datapoints, PlotOrientation.VERTICAL, true, true, false); + diamond = ShapeUtilities.createDiamond(2f); + chart.setBorderVisible(false); + chart.setAntiAlias(true); + chart.getPlot().setBackgroundPaint(Color.WHITE); + chart.setBorderVisible(false); + + + xyPlot = (XYPlot) chart.getPlot(); + xyPlot.setDomainCrosshairVisible(true); + xyPlot.setRangeCrosshairVisible(true); + + + renderer = (XYLineAndShapeRenderer) xyPlot.getRenderer(); + renderer.setSeriesLinesVisible(0, false); + renderer.setSeriesShapesVisible(0, true); + renderer.setSeriesLinesVisible(1, true); + renderer.setSeriesLinesVisible(1, true); + renderer.setSeriesPaint(0, Color.blue); + renderer.setSeriesShape(0, diamond); + renderer.setBaseSeriesVisible(true); + + + xyPlot.setDomainCrosshairVisible(true); + xyPlot.setRangeCrosshairVisible(true); + + panel = new ChartPanel(chart); + panel.setMouseZoomable(false); + this.add(panel, BorderLayout.CENTER); + } + + public void clear() { + if (datapoints != null) + datapoints.removeAllSeries(); + } + + public void addLineToPlot(double m, double b, Paint color, String name) { + + XYSeries linesA = new XYSeries(name); + linesA.add(min.doubleValue(), min * m + b); + linesA.add(max.doubleValue(), max * m + b); + + datapoints.addSeries(linesA); + + renderer.setSeriesPaint(seriesCount, color); + renderer.setSeriesStroke(seriesCount, new BasicStroke(2.0f)); + renderer.setBaseSeriesVisible(true); + renderer.setSeriesLinesVisible(seriesCount, true); + seriesCount++; + + } + + + public void addLineToPlot(double m, double b, String name) { + + + XYSeries linesA = new XYSeries(name); + linesA.add(min.doubleValue(), min * m + b); + linesA.add(max.doubleValue(), max * m + b); + + datapoints.addSeries(linesA); + seriesCount = xyPlot.getSeriesCount(); + renderer.setSeriesPaint(seriesCount, Color.red); + renderer.setSeriesStroke(seriesCount, new BasicStroke(2.0f)); + renderer.setBaseSeriesVisible(true); + renderer.setSeriesLinesVisible(seriesCount, true); + } + + private void convertData(LinkedList points) { + datapoints = new XYSeriesCollection(); + ArrayList coordinates = new ArrayList<>(); + series = new XYSeries("points"); + for (Line p : points) { + series.add(p.getM().doubleValue(), p.getB().doubleValue() * (-1)); + coordinates.add(p.getM()); + + } + this.max = series.getMaxX(); + this.min = series.getMinX(); + datapoints.addSeries(series); + } + + +} + diff --git a/src/main/java/view/panels/tabs/LMSPanel.java b/src/main/java/view/panels/tabs/LMSPanel.java new file mode 100644 index 0000000..561fe78 --- /dev/null +++ b/src/main/java/view/panels/tabs/LMSPanel.java @@ -0,0 +1,109 @@ +package view.panels.tabs; + +import com.sun.istack.internal.Nullable; +import view.panels.PlotPanel; + +import javax.swing.*; +import javax.swing.border.TitledBorder; +import java.awt.*; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 02.06.2017. + */ +public class LMSPanel extends TabPanel { + + + private JLabel[] labels; + private JTextField[] input; + private JPanel continer; + + private GridBagConstraints gbc; + + public LMSPanel() { + super(); + this.labels = new JLabel[2]; + this.input = new JTextField[2]; + + this.continer = new JPanel(); + this.continer.setLayout(new GridBagLayout()); + + this.gbc = new GridBagConstraints(); + this.gbc.anchor = GridBagConstraints.NORTH; + this.gbc.fill = GridBagConstraints.HORIZONTAL; + + addTextfieldAndInput(0, "Konstante", 0.5); + addTextfieldAndInput(1, "Fehler", 0.05); + + addButton(2, getStartButton()); + + getNorthPanel().add(continer, BorderLayout.CENTER); + this.add(getNorthPanel(), BorderLayout.NORTH); + this.add(getCenterPanel(), BorderLayout.CENTER); + } + + + @Override + protected void addTextfieldAndInput(int row, String name, Double value) { + this.labels[row] = new JLabel(name); + this.labels[row].setFont(new Font("SansSerif", Font.PLAIN, 12)); + this.input[row] = new JTextField(); + this.input[row].setText("" + value); + + gbc.insets = new Insets(0, 5, 0, 0); + gbc.gridx = 0; + gbc.gridy = row; + gbc.weightx = 0.05; + gbc.weighty = 0.05; + continer.add(this.labels[row], gbc); + + gbc.gridx = 1; + gbc.gridy = row; + gbc.weightx = 0.9; + gbc.weighty = 0.05; + gbc.insets = new Insets(0, 0, 0, 5); + continer.add(this.input[row], gbc); + } + + private void addButton(int row, JButton button) { + JPanel buttonPanel = new JPanel(); + buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); + + gbc.insets = new Insets(30, 0, 5, 0); + + gbc.gridx = 0; + gbc.gridy = row; + gbc.weightx = 0.05; + gbc.weighty = 0.05; + gbc.gridwidth = 1; + buttonPanel.add(button); + continer.add(buttonPanel, gbc); + } + + + @Nullable + public String[] getInput() { + String[] input = new String[3]; + input[0] = this.input[0].getText(); + input[1] = this.input[1].getText(); + + if (isNumeric(input[0]) && isNumeric(input[1])) { + return input; + } else { + JOptionPane.showMessageDialog(this, "Bitte geben Sie numerische Werte als Parameter an.", "Fehler bei der Eingabe", JOptionPane.ERROR_MESSAGE); + return null; + } + } + + 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/tabs/RMPanel.java b/src/main/java/view/panels/tabs/RMPanel.java new file mode 100644 index 0000000..0fc89d4 --- /dev/null +++ b/src/main/java/view/panels/tabs/RMPanel.java @@ -0,0 +1,104 @@ +package view.panels.tabs; + +import com.sun.istack.internal.Nullable; +import view.panels.PlotPanel; + +import javax.swing.*; +import javax.swing.border.TitledBorder; +import java.awt.*; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 21.06.2017. + */ +public class RMPanel extends TabPanel { + + private JLabel labels; + private JTextField input; + private JPanel continer; + private GridBagConstraints gbc; + + public RMPanel() { + super(); + this.labels = new JLabel(); + + this.input = new JTextField(); + this.setLayout(new BorderLayout()); + + + this.continer = new JPanel(); + this.continer.setLayout(new GridBagLayout()); + + this.gbc = new GridBagConstraints(); + this.gbc.anchor = GridBagConstraints.NORTH; + this.gbc.fill = GridBagConstraints.HORIZONTAL; + + addTextfieldAndInput(0, "\u00df (0 < \u00df < 1)", 0.5); + + + JPanel buttonPanel = new JPanel(); + buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); + gbc.insets = new Insets(30, 0, 10, 0); + gbc.gridx = 0; + gbc.gridy = 2; + gbc.weightx = 0.05; + gbc.weighty = 0.05; + buttonPanel.add(getStartButton()); + continer.add(buttonPanel, gbc); + + getNorthPanel().add(continer, BorderLayout.CENTER); + this.add(getNorthPanel(), BorderLayout.NORTH); + this.add(getCenterPanel(), BorderLayout.CENTER); + } + + @Override + protected void addTextfieldAndInput(int row, String name, Double value) { + this.labels = new JLabel(name); + this.labels.setFont(new Font("SansSerif", Font.PLAIN, 13)); + this.input = new JTextField(); + this.input.setText("" + value); + + gbc.insets = new Insets(0, 5, 0, 0); + gbc.gridx = 0; + gbc.gridy = row; + gbc.weightx = 0.05; + gbc.weighty = 0.05; + continer.add(this.labels, gbc); + + gbc.gridx = 1; + gbc.gridy = row; + gbc.weightx = 0.9; + gbc.weighty = 0.05; + gbc.insets = new Insets(0, 0, 0, 5); + continer.add(this.input, gbc); + } + + + @Nullable + public String getInput() { + String input = ""; + input = this.input.getText(); + if (isNumeric(input)) + return input; + else + JOptionPane.showMessageDialog(this, "Bitte geben Sie numerische Werte als Parameter an.", "Fehler bei der Eingabe", JOptionPane.ERROR_MESSAGE); + return null; + } + + public void setInput(JTextField input) { + this.input = input; + } + + + 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/tabs/TSPanel.java b/src/main/java/view/panels/tabs/TSPanel.java new file mode 100644 index 0000000..3151e9f --- /dev/null +++ b/src/main/java/view/panels/tabs/TSPanel.java @@ -0,0 +1,47 @@ +package view.panels.tabs; + +import com.sun.istack.internal.Nullable; +import view.panels.PlotPanel; + +import javax.swing.*; +import javax.swing.border.TitledBorder; +import java.awt.*; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 26.06.2017. + */ +public class TSPanel extends TabPanel { + + + private JPanel continer; + private GridBagConstraints gbc; + + public TSPanel() { + super(); + + this.continer = new JPanel(); + this.continer.setLayout(new GridBagLayout()); + + this.gbc = new GridBagConstraints(); + this.gbc.anchor = GridBagConstraints.NORTH; + this.gbc.fill = GridBagConstraints.HORIZONTAL; + + JPanel buttonPanel = new JPanel(); + buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); + + gbc.insets = new Insets(10, 0, 10, 0); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.weightx = 0.05; + gbc.weighty = 0.05; + buttonPanel.add(getStartButton()); + continer.add(buttonPanel, gbc); + + getNorthPanel().add(continer, BorderLayout.CENTER); + this.add(getNorthPanel(), BorderLayout.NORTH); + } +} diff --git a/src/main/java/view/panels/tabs/TabPanel.java b/src/main/java/view/panels/tabs/TabPanel.java new file mode 100644 index 0000000..a28b013 --- /dev/null +++ b/src/main/java/view/panels/tabs/TabPanel.java @@ -0,0 +1,86 @@ +package view.panels.tabs; + +import view.panels.PlotPanel; + +import javax.swing.*; +import javax.swing.border.TitledBorder; +import java.awt.*; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 10.09.2017. + */ +public abstract class TabPanel extends JPanel{ + + + private PlotPanel plotPanel; + private JPanel northPanel; + private JPanel centerPanel; + + private JButton startButton; + + public TabPanel() { + super(); + this.centerPanel = new JPanel(new BorderLayout()); + this.centerPanel.setBorder(new TitledBorder("Visualisierung")); + + this.setLayout(new BorderLayout()); + this.northPanel = new JPanel(new BorderLayout()); + this.centerPanel = new JPanel(new BorderLayout()); + this.northPanel.setBorder(new TitledBorder("Konfiguration")); + this.centerPanel.setBorder(new TitledBorder("Visualisierung")); + + + this.add(centerPanel, BorderLayout.CENTER); + this.add(northPanel, BorderLayout.NORTH); + + this.startButton = new JButton("Start"); + this.startButton.setFont(new Font("Verdana", Font.PLAIN, 16)); + } + + public void setPlotPanel(PlotPanel plotPanel) { + this.plotPanel = plotPanel; + if (this.centerPanel.getComponents().length > 0) + this.centerPanel.remove(0); + + this.centerPanel.add(plotPanel, BorderLayout.CENTER); + this.plotPanel.setVisible(true); + this.repaint(); + this.revalidate(); + } + + protected void addTextfieldAndInput(int row, String name, Double value){ + //muss nicht obligatorisch implementiert werden + } + + public PlotPanel getPlotPanel() { + return plotPanel; + } + + public JButton getStartButton() { + return startButton; + } + + public void setStartButton(JButton startButton) { + this.startButton = startButton; + } + + public JPanel getNorthPanel() { + return northPanel; + } + + public void setNorthPanel(JPanel northPanel) { + this.northPanel = northPanel; + } + + public JPanel getCenterPanel() { + return centerPanel; + } + + public void setCenterPanel(JPanel centerPanel) { + this.centerPanel = centerPanel; + } +} diff --git a/src/main/resources/Thumbs.db b/src/main/resources/Thumbs.db index b0530a0..9919d7e 100644 Binary files a/src/main/resources/Thumbs.db and b/src/main/resources/Thumbs.db differ diff --git a/src/main/resources/wwu.png b/src/main/resources/wwu.png new file mode 100644 index 0000000..05e6432 Binary files /dev/null and b/src/main/resources/wwu.png differ diff --git a/src/test/java/Model/DoublyConnectedEdgeListTest.java b/src/test/java/Model/DoublyConnectedEdgeListTest.java deleted file mode 100644 index 852f7e3..0000000 --- a/src/test/java/Model/DoublyConnectedEdgeListTest.java +++ /dev/null @@ -1,99 +0,0 @@ -package Model; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; - -import Model.DCEL.DoublyConnectedEdgeList; -import Model.DCEL.Edge; -import Model.DCEL.Face; -import Model.DCEL.Node; -import java.util.LinkedList; -import org.junit.Before; -import org.junit.Test; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 30.05.2017. - */ -public class DoublyConnectedEdgeListTest { - - private static DoublyConnectedEdgeList dcel; - private static Node v1, v2, v3, v4, v5; - private static Edge e1, e2, e3, e4, e5; - private static Face f1, f2; - - @Before - public void setUp() throws Exception { - dcel = new DoublyConnectedEdgeList(); - - //initialisiere die TestKnoten im Graphen - v1 = dcel.createNode(new Point(2.5, 7.5), "v1"); - v2 = dcel.createNode(new Point(2.5, 4.0), "v2"); - v3 = dcel.createNode(new Point(6.5, 3.5), "v3"); - v4 = dcel.createNode(new Point(8.5, 6.5), "v4"); - v5 = dcel.createNode(new Point(6.0, 8.0), "v5"); - - //initialisere Kanten im Graph - e1 = dcel.createEdge(v1, v5, "e1"); - e2 = dcel.createEdge(v5, v4, "e2"); - e3 = dcel.createEdge(v4, v3, "e3"); - e4 = dcel.createEdge(v3, v2, "e4"); - e5 = dcel.createEdge(v2, v1, "e5"); - - dcel.createConnection(e1, e2); - dcel.createConnection(e2, e3); - dcel.createConnection(e3, e4); - dcel.createConnection(e4, e5); - dcel.createConnection(e5, e1); - - //intialisiere die Flaechen - f1 = dcel.createFace(null, e1, "f1"); - f2 = dcel.createFace(e1.getTwin(), null, "f2"); - } - - - @Test - public void testInnerComponentsAccess() { - System.out.println("Test: testInnerComponentAccess();"); - Edge[] expected = {e1, e2, e3, e4, e5}; - LinkedList list = dcel.getEdgesOfInnerComponents(f1); - - assertArrayEquals(expected, list.toArray()); - } - - @Test - public void testOuterComponentsAccess() { - System.out.println("Test: testOuterComponentAccess();"); - String[] expected = {"#e1", "#e5", "#e4", "#e3", "#e2"}; - LinkedList list = dcel.getEdgesOfOuterComponents(f2); - - for (int i = 0; i < list.size(); i++) { - assertEquals(expected[i], list.get(i).getID()); - } - - } - - - @Test - public void testNodeEdgeAccess() { - System.out.println("Test: testNodeEdgeAccess();"); - - assertEquals(5, dcel.getConnectedEdges(v4).size()); - } - - @Test - public void testDCELAccess() { - System.out.println("Test: testDCELAccess();"); - - assertEquals(e1, e1.getTwin().getTwin()); - assertEquals(e1, e1.getPrev().getNext()); - assertEquals(e2.getID(), e1.getTwin().getPrev().getTwin().getID()); - assertEquals(e1, e1.getNext().getNext().getNext().getNext().getNext()); - assertEquals(e1.getTwin(), e1.getTwin().getNext().getNext().getNext().getNext().getNext()); - } - - -} \ No newline at end of file diff --git a/src/test/java/Presenter/Algorithms/LeastMedianOfSquaresEstimatorTest.java b/src/test/java/Presenter/Algorithms/LeastMedianOfSquaresEstimatorTest.java deleted file mode 100644 index b115460..0000000 --- a/src/test/java/Presenter/Algorithms/LeastMedianOfSquaresEstimatorTest.java +++ /dev/null @@ -1,119 +0,0 @@ -package Presenter.Algorithms; - - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import Model.Line; -import Model.Point; -import Model.Interval; - -import java.util.ArrayList; -import java.util.LinkedList; -import org.junit.Before; -import org.junit.Test; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 12.06.2017. - */ -public class LeastMedianOfSquaresEstimatorTest { - - private LeastMedianOfSquaresEstimator lms; - - @Before - public void setUp() throws Exception { - - Double[] x = {18d, 24d, 30d, 34d, 38d}; - Double[] y = {18d, 26d, 30d, 40d, 70d}; - - LinkedList lines = new LinkedList<>(); - LinkedList intersections = new LinkedList<>(); - - for (int i = 0; i < 5; i++) { - lines.add(new Line(x[i], y[i])); - } - - lms = new LeastMedianOfSquaresEstimator(lines, intersections); - } - - @Test - public void approximateLMS() throws Exception { - - } - - - @Test - public void mergeSort() throws Exception { -// double[] umin = {6,3,4,1,2,5}; -// double[] umax = {3,5,2,6,1,4}; - double[] umin = {1, 2, 3, 4}; - double[] umax = {2, 3, 4, 1}; - ArrayList a = new ArrayList<>(); - ArrayList b = new ArrayList<>(); - - for (double d : umin) { - a.add((int) d); - } - - for (double d : umax) { - b.add((int) d); - } - IntersectionCounter invCounter = new IntersectionCounter(); - int ret = invCounter.run(a, b); - assertEquals(3d, ret, 0.001); - - } - - @Test - public void geEjValues() throws Exception { - - Double[] expected = {36d, 50d, 60d, 74d, 108d}; - ArrayList actual = lms.getEjValues(1d); - assertArrayEquals(expected, actual.toArray()); - } - - @Test - public void calcKMinusBracelet() throws Exception { - - Point point = new Point(1d, 1d); - Double[] expected = {24d, 36d, 60d}; - Double[] actual = lms.calcKMinusBracelet(point, 3); - - assertArrayEquals(expected, actual); - - } - - @Test - public void upperBound() throws Exception { - lms.setkMinus(3); - lms.setHeightsigmaMin(500); - lms.setSigmaMin(new Line(0, 0, 0, 0)); - lms.setN(5); - Line expected = new Line(5, 5, 146, 210); - lms.upperBound(5d); - - assertEquals(expected.getX1(), lms.getSigmaMin().getX1(), 0.01); - assertEquals(expected.getX2(), lms.getSigmaMin().getX2(), 0.01); - assertEquals(expected.getY1(), lms.getSigmaMin().getY1(), 0.01); - assertEquals(expected.getY2(), lms.getSigmaMin().getY2(), 0.01); - } - - @Test - public void lowerBound() throws Exception { - //kann nur über sout geprüft werden test passt aber - Double[] expectedAlpha = {0d, 0d, 0d, 2d, 4d}; - Double[] expectedBeta = {2d, 4d, 4d, 2d, 1d}; - lms.setHeightsigmaMin(500); - - Interval interval = new Interval(-2, 0); - lms.lowerBound(interval); - assertTrue(interval.getActivity()); - } - - -} \ No newline at end of file diff --git a/src/test/java/Presenter/ImportExport/DataImporterTest.java b/src/test/java/Presenter/ImportExport/DataImporterTest.java deleted file mode 100644 index 161c77d..0000000 --- a/src/test/java/Presenter/ImportExport/DataImporterTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package Presenter.ImportExport; - -import org.junit.Before; -import org.junit.Test; - -/** - * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. - * - * @Author: Armin Wolf - * @Email: a_wolf28@uni-muenster.de - * @Date: 21.06.2017. - */ -public class DataImporterTest { - - private DataImporter importer; - - @Before - public void setUp() throws Exception { - //importer = new DataImporter("C:\\Users\\Armin\\Desktop\\test.csv", null); - } - - @Test - public void run() throws Exception { - //importer.run(); - } - -} \ No newline at end of file diff --git a/src/test/java/model/DoublyConnectedEdgeListTest.java b/src/test/java/model/DoublyConnectedEdgeListTest.java new file mode 100644 index 0000000..d3be8cd --- /dev/null +++ b/src/test/java/model/DoublyConnectedEdgeListTest.java @@ -0,0 +1,100 @@ +package model; + +import model.DCEL.DoublyConnectedEdgeList; +import model.DCEL.Edge; +import model.DCEL.Face; +import model.DCEL.Node; +import org.junit.Before; +import org.junit.Test; + +import java.util.LinkedList; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 30.05.2017. + */ +public class DoublyConnectedEdgeListTest { + + private static DoublyConnectedEdgeList dcel; + private static Node v1, v2, v3, v4, v5; + private static Edge e1, e2, e3, e4, e5; + private static Face f1, f2; + + @Before + public void setUp() throws Exception { + dcel = new DoublyConnectedEdgeList(); + + //initialisiere die TestKnoten im Graphen + v1 = dcel.createNode(new Point(2.5, 7.5), "v1"); + v2 = dcel.createNode(new Point(2.5, 4.0), "v2"); + v3 = dcel.createNode(new Point(6.5, 3.5), "v3"); + v4 = dcel.createNode(new Point(8.5, 6.5), "v4"); + v5 = dcel.createNode(new Point(6.0, 8.0), "v5"); + + //initialisere Kanten im Graph + e1 = dcel.createEdge(v1, v5, "e1"); + e2 = dcel.createEdge(v5, v4, "e2"); + e3 = dcel.createEdge(v4, v3, "e3"); + e4 = dcel.createEdge(v3, v2, "e4"); + e5 = dcel.createEdge(v2, v1, "e5"); + + dcel.createConnection(e1, e2); + dcel.createConnection(e2, e3); + dcel.createConnection(e3, e4); + dcel.createConnection(e4, e5); + dcel.createConnection(e5, e1); + + //intialisiere die Flaechen + f1 = dcel.createFace(null, e1, "f1"); + f2 = dcel.createFace(e1.getTwin(), null, "f2"); + } + + + @Test + public void testInnerComponentsAccess() { + System.out.println("Test: testInnerComponentAccess();"); + Edge[] expected = {e1, e2, e3, e4, e5}; + LinkedList list = dcel.getEdgesOfInnerComponents(f1); + + assertArrayEquals(expected, list.toArray()); + } + + @Test + public void testOuterComponentsAccess() { + System.out.println("Test: testOuterComponentAccess();"); + String[] expected = {"#e1", "#e5", "#e4", "#e3", "#e2"}; + LinkedList list = dcel.getEdgesOfOuterComponents(f2); + + for (int i = 0; i < list.size(); i++) { + assertEquals(expected[i], list.get(i).getID()); + } + + } + + + @Test + public void testNodeEdgeAccess() { + System.out.println("Test: testNodeEdgeAccess();"); + + assertEquals(5, dcel.getConnectedEdges(v4).size()); + } + + @Test + public void testDCELAccess() { + System.out.println("Test: testDCELAccess();"); + + assertEquals(e1, e1.getTwin().getTwin()); + assertEquals(e1, e1.getPrev().getNext()); + assertEquals(e2.getID(), e1.getTwin().getPrev().getTwin().getID()); + assertEquals(e1, e1.getNext().getNext().getNext().getNext().getNext()); + assertEquals(e1.getTwin(), e1.getTwin().getNext().getNext().getNext().getNext().getNext()); + } + + +} \ No newline at end of file diff --git a/src/test/java/presenter/algorithms/LeastMedianOfSquaresEstimatorTest.java b/src/test/java/presenter/algorithms/LeastMedianOfSquaresEstimatorTest.java new file mode 100644 index 0000000..9c9a41a --- /dev/null +++ b/src/test/java/presenter/algorithms/LeastMedianOfSquaresEstimatorTest.java @@ -0,0 +1,117 @@ +package presenter.algorithms; + + +import model.Interval; +import model.Line; +import model.Point; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.LinkedList; + +import static org.junit.Assert.*; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 12.06.2017. + */ +public class LeastMedianOfSquaresEstimatorTest { + + private LeastMedianOfSquaresEstimator lms; + + @Before + public void setUp() throws Exception { + + Double[] x = {18d, 24d, 30d, 34d, 38d}; + Double[] y = {18d, 26d, 30d, 40d, 70d}; + + LinkedList lines = new LinkedList<>(); + LinkedList intersections = new LinkedList<>(); + + for (int i = 0; i < 5; i++) { + lines.add(new Line(x[i], y[i])); + } + + lms = new LeastMedianOfSquaresEstimator(lines, intersections); + } + + @Test + public void approximateLMS() throws Exception { + + } + + + @Test + public void mergeSort() throws Exception { +// double[] umin = {6,3,4,1,2,5}; +// double[] umax = {3,5,2,6,1,4}; + double[] umin = {1, 2, 3, 4}; + double[] umax = {2, 3, 4, 1}; + ArrayList a = new ArrayList<>(); + ArrayList b = new ArrayList<>(); + + for (double d : umin) { + a.add((int) d); + } + + for (double d : umax) { + b.add((int) d); + } + IntersectionCounter invCounter = new IntersectionCounter(); + int ret = invCounter.run(a, b); + assertEquals(3d, ret, 0.001); + + } + + @Test + public void geEjValues() throws Exception { + + Double[] expected = {36d, 50d, 60d, 74d, 108d}; + ArrayList actual = lms.getEjValues(1d); + assertArrayEquals(expected, actual.toArray()); + } + + @Test + public void calcKMinusBracelet() throws Exception { + + Point point = new Point(1d, 1d); + Double[] expected = {24d, 36d, 60d}; + Double[] actual = lms.calcKMinusBracelet(point, 3); + + assertArrayEquals(expected, actual); + + } + + @Test + public void upperBound() throws Exception { + lms.setkMinus(3); + lms.setHeightsigmaMin(500); + lms.setSigmaMin(new Line(0, 0, 0, 0)); + lms.setN(5); + Line expected = new Line(5, 5, 146, 210); + lms.upperBound(5d); + + assertEquals(expected.getX1(), lms.getSigmaMin().getX1(), 0.01); + assertEquals(expected.getX2(), lms.getSigmaMin().getX2(), 0.01); + assertEquals(expected.getY1(), lms.getSigmaMin().getY1(), 0.01); + assertEquals(expected.getY2(), lms.getSigmaMin().getY2(), 0.01); + } + + @Test + public void lowerBound() throws Exception { + //kann nur über sout geprüft werden test passt aber + Double[] expectedAlpha = {0d, 0d, 0d, 2d, 4d}; + Double[] expectedBeta = {2d, 4d, 4d, 2d, 1d}; + lms.setHeightsigmaMin(500); + + Interval interval = new Interval(-2, 0); + lms.lowerBound(interval); + assertTrue(interval.getActivity()); + } + + +} \ No newline at end of file diff --git a/src/test/java/presenter/io/DataImporterTest.java b/src/test/java/presenter/io/DataImporterTest.java new file mode 100644 index 0000000..e70abc5 --- /dev/null +++ b/src/test/java/presenter/io/DataImporterTest.java @@ -0,0 +1,27 @@ +package presenter.io; + +import org.junit.Before; +import org.junit.Test; + +/** + * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden. + * + * @Author: Armin Wolf + * @Email: a_wolf28@uni-muenster.de + * @Date: 21.06.2017. + */ +public class DataImporterTest { + + private DataImporter importer; + + @Before + public void setUp() throws Exception { + //importer = new DataImporter("C:\\Users\\Armin\\Desktop\\test.csv", null); + } + + @Test + public void run() throws Exception { + //importer.run(); + } + +} \ No newline at end of file