194 lines
5.5 KiB
Java
194 lines
5.5 KiB
Java
package de.wwwu.awolf.presenter.util;
|
|
|
|
import de.wwwu.awolf.model.Interval;
|
|
import de.wwwu.awolf.model.Line;
|
|
import de.wwwu.awolf.model.Point;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
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 List<Line> lines;
|
|
private Set<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(List<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) {
|
|
Logging.logError(e.getMessage(), e);
|
|
Thread.currentThread().interrupt();
|
|
}
|
|
}
|
|
} 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 List<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) {
|
|
return intersections.contains(p);
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
}
|