parent
77ad52ee53
commit
ce49fceeee
File diff suppressed because it is too large
Load Diff
@ -1,252 +0,0 @@
|
||||
package de.wwwu.awolf.presenter.util;
|
||||
|
||||
import de.wwwu.awolf.model.Interval;
|
||||
import de.wwwu.awolf.model.Line;
|
||||
import de.wwwu.awolf.model.Pair;
|
||||
import de.wwwu.awolf.model.Point;
|
||||
import de.wwwu.awolf.presenter.util.Comparators.YOrderLineComparatorBegin;
|
||||
import de.wwwu.awolf.presenter.util.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<Integer, Integer> dictionaryTO;
|
||||
private HashMap<Integer, Integer> dictionaryBACK;
|
||||
private ArrayList<Integer> substituted;
|
||||
private ArrayList<Pair> inversions;
|
||||
private List<Line> set;
|
||||
|
||||
//indexieren der Punkte damit die schnittpunkte berechnet werden können
|
||||
private HashMap<Line, Integer> secondaryDictionaryTO;
|
||||
private HashMap<Integer, Line> secondaryDictionaryBACK;
|
||||
private ArrayList<Line> umin;
|
||||
|
||||
|
||||
/**
|
||||
* Berechnet die Inversionen zwischen zwei Listen mit Integer Werten. Diese Methode dient als
|
||||
* Wrapper Methode. Die Logik steht in der <code>countInversions</code> Funktion.
|
||||
*
|
||||
* @param a Liste
|
||||
* @param b Liste
|
||||
* @return Anzahl an Inversionen
|
||||
*/
|
||||
public int run(List<Integer> a, List<Integer> b) {
|
||||
|
||||
dictionaryTO = new HashMap<>();
|
||||
dictionaryBACK = new HashMap<>();
|
||||
substituted = new ArrayList<>();
|
||||
inversions = new ArrayList<>();
|
||||
|
||||
ArrayList<Integer> 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<Line> set, Interval interval) {
|
||||
ArrayList<Integer> listA = new ArrayList<>();
|
||||
ArrayList<Integer> listB = new ArrayList<>();
|
||||
|
||||
prepareData(set, interval, listA, listB);
|
||||
return run(listA, listB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Methode die, die Daten für die Funktion <code>run</code> 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<Line> set, Interval interval, ArrayList<Integer> listA,
|
||||
ArrayList<Integer> 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<Integer> a, int start, int end, List<Integer> 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
|
||||
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++) {
|
||||
// Logging.logInfo(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 <code>run</code> Funktion Sinnvolle Werte.
|
||||
*/
|
||||
public ArrayList<Point> calculateIntersectionAbscissas() {
|
||||
ArrayList<Pair> result = new ArrayList<>();
|
||||
|
||||
ArrayList<Point> points = 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();
|
||||
Point point = new Point(intersection, yintercept);
|
||||
points.add(point);
|
||||
}
|
||||
}
|
||||
|
||||
return points;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 List<Double> calculateIntersectionAbscissas(List<Line> set, Line sampledLine, double lower, double upper) {
|
||||
List<Line> lines = new LinkedList<>(set);
|
||||
Set<Double> intersections = new HashSet<>();
|
||||
|
||||
for (Line line : lines) {
|
||||
if (line != sampledLine) {
|
||||
if (sampledLine.doIntersect(line, lower, upper)){
|
||||
intersections.add(sampledLine.intersect(line).getX());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new ArrayList<>(intersections);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 List<Double> calculateIntersectionYInterception(List<Line> set, Line sampledLine, double lower, double upper) {
|
||||
List<Line> lines = new LinkedList<>(set);
|
||||
Set<Double> intersections = new HashSet<>();
|
||||
|
||||
for (Line line : lines) {
|
||||
if (line != sampledLine) {
|
||||
if (sampledLine.doIntersect(line, lower, upper)){
|
||||
intersections.add(sampledLine.intersect(line).getY());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new ArrayList<>(intersections);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
Loading…
Reference in new issue