algorithms-for-computing-li.../src/main/java/de/wwwu/awolf/model/Line.java

298 lines
7.3 KiB
Java

package de.wwwu.awolf.model;
import java.util.Objects;
import org.apache.commons.math3.util.Precision;
/**
* Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
*
* @Author: Armin Wolf
* @Email: a_wolf28@uni-muenster.de
* @Date: 12.06.2017.
*/
public class Line implements Comparable<Line> {
private static final double EPSILON = 0.00001;
private static final double MIN = 9999d;
private static final double MAX = -9999d;
private Double m;
private Double b;
private Double x1;
private Double x2;
private Double y1;
private Double y2;
private String id;
/**
* Konstruktor
*
* @param m Steigung
* @param b y-Achsenabschnitt
* @param id id
*/
public Line(double m, double b, String id) {
this.m = m;
this.b = b;
this.x1 = MAX;
this.y1 = (MAX * m) + b;
this.x2 = MIN * 0.5;
this.y2 = ((MIN * 0.5) * m) + b;
this.id = id;
}
/**
* Konstruktor
*
* @param m Steigung
* @param b y-Achsenabschnitt
*/
public Line(double m, double b) {
this.m = m;
this.b = b;
this.x1 = calculateX1(MAX);
this.y1 = calculateY1(MAX);
this.x2 = calculateX2(MIN * 0.5);
this.y2 = calculateY2(MIN * 0.5);
}
/**
* Konstruktor
*
* @param x1 x-Koordiante des Startpunkts
* @param x2 x-Koordinate des Endpunkts
* @param y1 y-Koordinate des Startpunkts
* @param y2 y-Koordinate des Endpunkts
*/
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 calculateX1(Double min) {
return min;
}
public Double calculateY1(Double min) {
return (min * (m * -1)) + b;
}
public Double calculateX2(Double max) {
return max;
}
public Double calculateY2(Double max) {
return (max * (m * -1)) + b;
}
/**
* @return Steigung der Gerade
*/
public Double getM() {
return m;
}
/**
* @param m Steigung der Gerade
*/
public void setM(double m) {
this.m = m;
}
/**
* @return y-Achsenabschnitt der Gerade
*/
public Double getB() {
return b;
}
/**
* @param b y-Achsenabschnitt der Gerade
*/
public void setB(double b) {
this.b = b;
}
/**
* @return id der Gerade
*/
public String getId() {
return id;
}
/**
* @param id id der Gerade
*/
public void setId(String id) {
this.id = id;
}
/**
* @return x-Koordiante des Startpunkts
*/
public Double getX1() {
return x1;
}
/**
* @return x-Koordiante des Endpunkts
*/
public Double getX2() {
return x2;
}
/**
* @return y-Koordiante des Startpunkts
*/
public Double getY1() {
return y1;
}
/**
* @return y-Koordiante des Endpunkts
*/
public Double getY2() {
return y2;
}
/**
* Setzt die Koordianten des Segments. Aus dem Segment wird eine Gerade berechnet.
*
* @param x1 x-Koordiante des Startpunkts
* @param y1 y-Koordiante des Endpunkts
* @param x2 x-Koordinate des Startpunkts
* @param y2 y-Koordinte des Endpunkts
*/
public void setEndPoints(double x1, double y1, double x2, 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);
}
/**
* Vergleich einzelner Geradern
*
* @param obj zu vergleichende Gerade
* @return <code>true</code> falls die Geraden Gleich sind
*/
@Override
public boolean equals(Object obj) {
if (obj instanceof Line) {
Line other = (Line) obj;
return Precision.equals(other.getM(), this.getM(), EPSILON) && Precision
.equals(other.getB(), this.getB(), EPSILON);
} else {
return super.equals(obj);
}
}
@Override
public int hashCode() {
return Objects.hash(Precision.round(m, 5), Precision.round(b, 5));
}
@Override
public String toString() {
return "Line m: " + this.getM() + ", b: " + this.getB();
}
public Point intersect(Line line) {
double x = (line.b - this.b) / (this.m - line.m);
double y = this.m * x + this.b;
return new Point(x, y);
}
// Given three colinear points p, q, r, the function checks if
// point q lies on line segment 'pr'
public boolean onSegment(Point p, Point q, Point r) {
return q.getX() <= Math.max(p.getX(), r.getX()) && q.getX() >= Math
.min(p.getX(), r.getX()) &&
q.getY() <= Math.max(p.getY(), r.getY()) && q.getY() >= Math
.min(p.getY(), r.getY());
}
// To find orientation of ordered triplet (p, q, r).
// The function returns following values
// 0 --> p, q and r are colinear
// 1 --> Clockwise
// 2 --> Counterclockwise
public int orientation(Point p, Point q, Point r) {
// See https://www.geeksforgeeks.org/orientation-3-ordered-points/
// for details of below formula.
double val = (q.getY() - p.getY()) * (r.getX() - q.getX()) -
(q.getX() - p.getX()) * (r.getY() - q.getY());
if (val == 0) {
return 0; // colinear
}
return (val > 0) ? 1 : 2; // clock or counterclock wise
}
// The main function that returns true if line segment 'p1q1'
// and 'p2q2' intersect.
// Line A: y = mx + b -->
public boolean doIntersect(Line line, double lower, double upper) {
//this
Point p1 = new Point(calculateX1(lower), calculateY1(lower));
Point q1 = new Point(calculateX2(upper), calculateY2(upper));
Point p2 = new Point(line.calculateX1(lower), line.calculateY1(lower));
Point q2 = new Point(line.calculateX2(upper), line.calculateY2(upper));
// Find the four orientations needed for general and
// special cases
int o1 = orientation(p1, q1, p2);
int o2 = orientation(p1, q1, q2);
int o3 = orientation(p2, q2, p1);
int o4 = orientation(p2, q2, q1);
// General case
if (o1 != o2 && o3 != o4) {
return true;
}
// Special Cases
// p1, q1 and p2 are colinear and p2 lies on segment p1q1
if (o1 == 0 && onSegment(p1, p2, q1)) {
return true;
}
// p1, q1 and q2 are colinear and q2 lies on segment p1q1
if (o2 == 0 && onSegment(p1, q2, q1)) {
return true;
}
// p2, q2 and p1 are colinear and p1 lies on segment p2q2
if (o3 == 0 && onSegment(p2, p1, q2)) {
return true;
}
// p2, q2 and q1 are colinear and q1 lies on segment p2q2
return o4 == 0 && onSegment(p2, q1, q2);// Doesn't fall in any of the above cases
}
@Override
public int compareTo(Line line) {
if (Precision.compareTo(this.getM(), line.getM(), EPSILON) == 0) {
return this.getB().compareTo(line.getB());
} else {
return this.getM().compareTo(line.getM());
}
}
}