algorithms-for-computing-li.../LinearRegressionTool/src/main/java/presenter/util/IntersectionComputer.java

185 lines
5.4 KiB
Java

package presenter.util;
import model.Interval;
import model.Line;
import model.Point;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeSet;
/**
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
*
* @Author: Armin Wolf
* @Email: a_wolf28@uni-muenster.de
* @Date: 18.09.2017.
*/
public class IntersectionComputer {
private LinkedList<Line> lines;
private TreeSet<Point> intersections;
private Double xMinimum;
private Double xMaximum;
private Double yMinimum;
private Double yMaximum;
private Thread[] worker;
/**
* Konstruktor
* @param lines Liste der Geraden
*/
public IntersectionComputer(LinkedList<Line> lines) {
this.lines = lines;
this.worker = new Thread[4];
this.intersections = new TreeSet<>();
xMinimum = Double.MAX_VALUE;
xMaximum = Double.MIN_VALUE;
yMinimum = Double.MAX_VALUE;
yMaximum = Double.MIN_VALUE;
}
/**
* Berechnet zu einer gegebenen Menge von dualen Geraden die Schnittpunkte. Dafür wird ein modifizierter Merge-Sort
* Algorithmus verwendett. Um die Performance zu steigern wird die Berechnung ab einer passenden Größe auf vier
* Threads ausgelagert.
* @param lower untere Schranke
* @param higher obere Schranke
* @return Liste der Schnittpunkte
*/
public ArrayList<Point> compute(final double lower, final double higher) {
if (lines.size() > 16) {
worker[0] = new Thread(() -> {
work(lines.subList(0, (lines.size() / 4)),lower,higher);
});
worker[0].start();
worker[1] = new Thread(() -> {
work(lines.subList((lines.size() / 4) + 1, (lines.size() / 2)),lower,higher);
});
worker[1].start();
worker[2] = new Thread(() -> {
work(lines.subList((lines.size() / 2) + 1, 3 * (lines.size() / 4)),lower,higher);
});
worker[2].start();
worker[3] = new Thread(() -> {
work(lines.subList(3 * (lines.size() / 4) + 1, (lines.size())),lower,higher);
});
worker[3].start();
for (Thread t : worker) {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} else {
work(lines,lower,higher);
}
return new ArrayList<>(intersections);
}
/**
* Berechnet zu einer gegebenen Menge von dualen Geraden die Schnittpunkte. Dafür wird ein modifizierter Merge-Sort
* Algorithmus verwendett. Um die Performance zu steigern wird die Berechnung ab einer passenden Größe auf vier
* Threads ausgelagert.
* @return Liste der Schnittpunkte
*/
public ArrayList<Point> compute() {
return compute(-99999, 99999);
}
private void work(List<Line> lines, double lower, double higher) {
IntersectionCounter counter = new IntersectionCounter();
int count = counter.run(lines, new Interval(lower, higher));
ArrayList<Point> points = counter.calculateIntersectionAbscissas();
for (Point p : points) {
if (!isFound(p)) {
addIntersection(p);
setRanges(p);
}
}
}
/**
* Synchronisierter Zugriff auf die Liste der Geraden
* @return Liste der Geraden
*/
public synchronized LinkedList<Line> getLines() {
return lines;
}
/**
* Synchronisierter hinzufügen eines Schnittpunkts
* @param p Schnittpunkt
*/
public synchronized void addIntersection(Point p) {
this.intersections.add(p);
}
/**
* Synchronisiertes abfragen ob ein Schnittpunkt bereits gefunden wurde.
* @param p Schnittpunkt
* @return <code>true</code>, falls der Schnittpunkt p bereits gefunden wurde
*/
public synchronized boolean isFound(Point p) {
if (intersections.contains(p)) {
return true;
} else {
return false;
}
}
/**
* Zu einem Punkt werden die minimalen, maximalen x- und y-Koordinaten überprüft und ggf.
* neu gesetzt
* @param point Schnittpunkt
*/
public void setRanges(Point point) {
xMaximum = (point.getX() > xMaximum) ? point.getX() : xMaximum;
xMinimum = (point.getX() < xMinimum) ? point.getX() : xMinimum;
yMaximum = (point.getY() > yMaximum) ? point.getY() : yMaximum;
yMinimum = (point.getY() < yMinimum) ? point.getY() : yMinimum;
}
/**
* Synchronisierter Zugriff auf die minimale x-Koordiante
* @return minimale x-Koordiante
*/
public synchronized Double getxMinimum() {
return xMinimum;
}
/**
* Synchronisierter Zugriff auf die maximale x-Koordinate
* @return maximale x-Koordinate
*/
public synchronized Double getxMaximum() {
return xMaximum;
}
/**
* Synchronisierter Zugriff auf die minimale y-Koordinate
* @return minimale y-Koordinate
*/
public synchronized Double getyMinimum() {
return yMinimum;
}
/**
* Synchronisierter Zugriff auf die maximale y-Koordinate
* @return maximale y-Koordinate
*/
public synchronized Double getyMaximum() {
return yMaximum;
}
}