package pl.edu.agh.spatial;
import static pl.edu.agh.spatial.HaversineDistanceCalculator.EARTH_DISTANCE_CALCULATOR;
import java.util.List;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.Ordering;
import com.google.common.collect.UnmodifiableIterator;
import com.google.common.collect.UnmodifiableListIterator;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.LineSegment;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.Point;
public class LineSegmentList implements Iterable<LineSegment> {
private ImmutableList<LineSegment> lines;
private double length;
public LineSegmentList(LineString lineString) {
ImmutableList.Builder<LineSegment> listBuilder = new Builder<LineSegment>();
Coordinate[] coords = lineString.getCoordinates();
for (int i = 1; i < coords.length; i++) {
listBuilder.add(new LineSegment(coords[i - 1], coords[i]));
}
lines = listBuilder.build();
calculateLength();
}
public LineSegmentList(List<LineString> segments) {
ImmutableList.Builder<LineSegment> listBuilder = new Builder<LineSegment>();
for (LineString segment : segments) {
listBuilder.add(new LineSegment(segment.getStartPoint().getCoordinate(), segment.getEndPoint()
.getCoordinate()));
}
lines = listBuilder.build();
calculateLength();
}
private void calculateLength() {
length = 0.0;
for (LineSegment segment : lines) {
length += EARTH_DISTANCE_CALCULATOR.distance(segment.p0, segment.p1);
}
}
@Override
public UnmodifiableIterator<LineSegment> iterator() {
return lines.iterator();
}
public UnmodifiableListIterator<LineSegment> listIterator() {
return lines.listIterator();
}
public LineSegment nearestLine(final Coordinate point) {
Ordering<LineSegment> byDistanceToLocation = new Ordering<LineSegment>() {
@Override
public int compare(LineSegment left, LineSegment right) {
return Double
.compare(left.distance(point), right.distance(point));
}
};
return byDistanceToLocation.min(lines);
}
public LineSegment nearestLine(final Point point) {
return nearestLine(point.getCoordinate());
}
public Coordinate nearestPoint(Coordinate point) {
return nearestLine(point).closestPoint(point);
}
public Coordinate nearestPoint(Point point) {
return nearestPoint(point.getCoordinate());
}
public double getLength() {
return length;
}
public Coordinate getStartPoint() {
return lines.get(0).p0;
}
public Coordinate getEndPoint() {
return lines.get(lines.size() - 1).p1;
}
}