/** * ***************************************************************************** * Copyright 2013 Johannes Mitlmeier * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * **************************************************************************** */ package de.fub.agg2graph.structs; import de.fub.agg2graph.agg.AggConnection; import java.util.Iterator; import java.util.TreeSet; /** * An edge in the gps data structures. * * @author Johannes Mitlmeier * */ public class GPSEdge extends AbstractEdge<GPSPoint> implements Comparable<GPSEdge> { public GPSEdge() { super(); } public GPSEdge(GPSPoint from, GPSPoint to) { this.setFrom(from); this.setTo(to); } /** * Constructor from GPSPoint and distance * * @param from * @param to * @param distance */ public GPSEdge(GPSPoint from, GPSPoint to, float distance) { super(from, to, distance); } /** * Constructor from AggConnection * * @param aggConnection */ public GPSEdge(AggConnection aggConnection) { this.setFrom(aggConnection.getFrom()); this.setTo(aggConnection.getTo()); } /** * TODO MARTINUS * * * @return */ public GPSRegion getRegion() { return new GPSRegion(getFrom(), getTo()); } @Override public float getDistance() { if (distance == 0) { this.distance = (float) getFrom().getDistanceTo(getTo()); } return distance; } public GPSPoint at(double t) { return new GPSPoint((1 - t) * from.getLat() + t * to.getLat(), (1 - t) * from.getLon() + t * to.getLon()); } public double getNearestDistance(GPSEdge ed) { double gradient1 = this.getGradient(); double gradient2 = ed.getGradient(); double interception1 = this.getInterception(); double interception2 = ed.getInterception(); double sliceX = (interception1 - interception2) / (gradient2 - gradient1); if ((this.getTo().getLon() < sliceX && sliceX < this.getFrom().getLon()) || (this.getTo().getLon() > sliceX && sliceX > this.getFrom() .getLon())) { return (0.0); } else { TreeSet<Double> distances = retrieveDistances(ed); return distances.first(); } } public double getFarestDistance(GPSEdge ed) { TreeSet<Double> distances = retrieveDistances(ed); return distances.last(); } public double getAverageDistance(GPSEdge ed) { TreeSet<Double> distances = retrieveDistances(ed); Iterator<Double> distIt = distances.iterator(); double avg = 0.0; int cnt = 0; while (distIt.hasNext()) { avg = (avg * cnt + distIt.next()) / (cnt + 1); cnt++; } return avg; } public TreeSet<Double> retrieveDistances(GPSEdge ed) { double gradient1; double gradient2; double interception1; double interception2; double sliceX; gradient1 = this.getGradient(); gradient2 = ed.getGradient(); interception1 = this.getInterception(); interception2 = ed.getInterception(); double interceptionFrom1Per2 = this.getFrom().getLat() - this.getFrom().getLon() * (1 / gradient2); double interceptionFrom2Per1 = ed.getFrom().getLat() - ed.getFrom().getLon() * (1 / gradient1); double interceptionTo1Per2 = this.getTo().getLat() - this.getTo().getLon() * (1 / gradient2); double interceptionTo2Per1 = ed.getTo().getLat() - ed.getTo().getLon() * (1 / gradient1); TreeSet<Double> distances = new TreeSet<Double>(); sliceX = (interceptionFrom1Per2 - interception2) / (gradient2 - (1 / gradient2)); if ((ed.getTo().getLon() < sliceX && sliceX < ed.getFrom().getLon()) || (ed.getTo().getLon() > sliceX && sliceX > ed.getFrom() .getLon())) { double latSlice = interceptionFrom1Per2 + (1 / gradient2) * sliceX; double latDist = Math.abs(latSlice - this.getFrom().getLat()); double longDist = Math.abs(sliceX - this.getFrom().getLon()); double dist = Math.sqrt(latDist * latDist + longDist * longDist); distances.add(dist); } sliceX = (interceptionFrom2Per1 - interception1) / (gradient1 - (1 / gradient1)); if ((this.getTo().getLon() < sliceX && sliceX < this.getFrom().getLon()) || (this.getTo().getLon() > sliceX && sliceX > this.getFrom() .getLon())) { double latSlice = interceptionFrom2Per1 + (1 / gradient1) * sliceX; double latDist = Math.abs(latSlice - ed.getFrom().getLat()); double longDist = Math.abs(sliceX - ed.getFrom().getLon()); double dist = Math.sqrt(latDist * latDist + longDist * longDist); distances.add(dist); } sliceX = (interceptionTo1Per2 - interception2) / (gradient2 - (1 / gradient2)); if ((ed.getTo().getLon() < sliceX && sliceX < ed.getFrom().getLon()) || (ed.getTo().getLon() > sliceX && sliceX > ed.getFrom() .getLon())) { double latSlice = interceptionTo1Per2 + (1 / gradient2) * sliceX; double latDist = Math.abs(latSlice - this.getTo().getLat()); double longDist = Math.abs(sliceX - this.getTo().getLon()); double dist = Math.sqrt(latDist * latDist + longDist * longDist); distances.add(dist); } sliceX = (interceptionTo2Per1 - interception1) / (gradient1 - (1 / gradient1)); if ((this.getTo().getLon() < sliceX && sliceX < this.getFrom().getLon()) || (this.getTo().getLon() > sliceX && sliceX > this.getFrom() .getLon())) { double latSlice = interceptionTo2Per1 + (1 / gradient1) * sliceX; double latDist = Math.abs(latSlice - ed.getTo().getLat()); double longDist = Math.abs(sliceX - ed.getTo().getLon()); double dist = Math.sqrt(latDist * latDist + longDist * longDist); distances.add(dist); } double latDist = Math.abs(this.getTo().getLat() - ed.getTo().getLat()); double longDist = Math.abs(this.getTo().getLon() - ed.getTo().getLon()); double dist = Math.sqrt(latDist * latDist + longDist * longDist); distances.add(dist); latDist = Math.abs(this.getTo().getLat() - ed.getFrom().getLat()); longDist = Math.abs(this.getTo().getLon() - ed.getFrom().getLon()); dist = Math.sqrt(latDist * latDist + longDist * longDist); distances.add(dist); latDist = Math.abs(this.getFrom().getLat() - ed.getTo().getLat()); longDist = Math.abs(this.getFrom().getLon() - ed.getTo().getLon()); dist = Math.sqrt(latDist * latDist + longDist * longDist); distances.add(dist); latDist = Math.abs(this.getFrom().getLat() - ed.getFrom().getLat()); longDist = Math.abs(this.getFrom().getLon() - ed.getFrom().getLon()); dist = Math.sqrt(latDist * latDist + longDist * longDist); distances.add(dist); return distances; } public double getGradient() { return (this.getFrom().getLat() - this.getTo().getLat()) / (this.getFrom().getLon() - this.getTo().getLon()); } public double getAngle() { double angle = Math.toDegrees(Math.atan((this.getEuDistance() * this.getEuDistance() + this.getLatDistance() * this.getLatDistance() - this.getLongDistance() * this.getLongDistance()) / (2 * this.getEuDistance() * this.getLatDistance()))); angle = Math.toDegrees(Math.atan(this.getLatDistance() / this.getLongDistance())); if (this.getTo().getLat() > this.getFrom().getLat()) { if (this.getTo().getLon() > this.getFrom().getLon()) { // correction on angle in order to have full 360 degrees: 90 // minus angle angle = 90 - angle; } else { // 270 plus angle angle = 270 + angle; } } else { if (this.getTo().getLon() > this.getFrom().getLon()) { // 180 minus angle angle = 90 + angle; } else { // 180 plus angle angle = 270 - angle; } } return angle; } private double getLatDistance() { return Math.abs(this.getTo().getLat() - this.getFrom().getLat()); } private double getLongDistance() { return Math.abs(this.getTo().getLon() - this.getFrom().getLon()); } public double getInterception() { return this.getFrom().getLat() - this.getFrom().getLon() * this.getGradient(); } @Override public String toString() { return this.getFrom() + "->" + this.getTo(); } public Double getEuDistance() { return this.getFrom().getDistanceTo(this.getTo()); } public double getSquaredEulerDistance() { return this.getFrom().getSquaredDistanceTo(this.getTo()); } public GPSEdge[] divide(GPSPoint middle) { GPSEdge[] ret = new GPSEdge[2]; //TODO check whether middle is in line setTo(middle); ret[0] = this; ret[1] = new GPSEdge(middle, to); return ret; } @Override public int compareTo(GPSEdge o) { if (o == null) { throw new NullPointerException(); } int r = getFrom().compareTo(o.getFrom()); if (r == 0) { return getTo().compareTo(o.getTo()); } else { return r; } } }