package com.revolsys.geometry.algorithm;
import com.revolsys.geometry.model.LineString;
import com.revolsys.geometry.model.Point;
import com.revolsys.geometry.model.impl.PointDoubleXY;
/**
* Represents a location along a {@link LineString}.
*/
public class LineStringLocation implements Comparable<LineStringLocation> {
private final LineString line;
private final double segmentFraction;
private final int segmentIndex;
private final double distance;
public LineStringLocation(final LineString line, final int segmentIndex,
final double segmentFraction, final double distance) {
this.line = line;
final int vertexCount = line.getVertexCount();
if (segmentIndex < 0) {
this.segmentIndex = 0;
this.segmentFraction = 0.0;
} else if (segmentIndex >= vertexCount) {
this.segmentIndex = vertexCount - 1;
this.segmentFraction = 1.0;
} else {
this.segmentIndex = segmentIndex;
if (segmentFraction < 0.0) {
this.segmentFraction = 0.0;
} else if (segmentFraction > 1.0) {
this.segmentFraction = 1.0;
} else {
this.segmentFraction = segmentFraction;
}
}
this.distance = distance;
}
/**
* Compares this object with the specified object for order.
*
* @param o the <code>LineStringLocation</code> with which this
* <code>Coordinate</code> is being compared
* @return a negative integer, zero, or a positive integer as this
* <code>LineStringLocation</code> is less than, equal to, or greater
* than the specified <code>LineStringLocation</code>
*/
@Override
public int compareTo(final LineStringLocation other) {
if (this.segmentIndex < other.segmentIndex) {
return -1;
} else if (this.segmentIndex > other.segmentIndex) {
return 1;
} else if (this.segmentFraction < other.segmentFraction) {
return -1;
} else if (this.segmentFraction > other.segmentFraction) {
return 1;
} else {
return 0;
}
}
public double getDistance() {
return this.distance;
}
public LineString getLine() {
return this.line;
}
public Point getPoint() {
final double x1 = this.line.getX(this.segmentIndex);
final double y1 = this.line.getY(this.segmentIndex);
if (this.segmentFraction == 0) {
return this.line.getPoint(this.segmentIndex);
} else {
final double x2 = this.line.getX(this.segmentIndex + 1);
final double y2 = this.line.getY(this.segmentIndex + 1);
if (this.segmentFraction == 0) {
return this.line.getPoint(this.segmentIndex + 1);
} else {
final double x = (x2 - x1) * this.segmentFraction + x1;
final double y = (y2 - y1) * this.segmentFraction + y1;
return new PointDoubleXY(this.line.getGeometryFactory(), x, y);
}
}
}
public Point getPoint2d() {
final double x1 = this.line.getX(this.segmentIndex);
final double y1 = this.line.getY(this.segmentIndex);
if (this.segmentFraction == 0) {
return new PointDoubleXY(x1, y1);
} else {
final double x2 = this.line.getX(this.segmentIndex + 1);
final double y2 = this.line.getY(this.segmentIndex + 1);
if (this.segmentFraction == 0) {
return new PointDoubleXY(x2, y2);
} else {
final double x = (x2 - x1) * this.segmentFraction + x1;
final double y = (y2 - y1) * this.segmentFraction + y1;
return new PointDoubleXY(this.line.getGeometryFactory(), x, y);
}
}
}
public double getSegmentFraction() {
return this.segmentFraction;
}
public int getSegmentIndex() {
return this.segmentIndex;
}
public int getVertexIndex() {
if (this.segmentFraction == 1) {
return this.segmentIndex + 1;
} else {
return this.segmentIndex;
}
}
public boolean isFromVertex() {
return this.segmentIndex == 0 && this.segmentFraction == 0.0;
}
public boolean isToVertex() {
final int lastSegmentIndex = this.line.getVertexCount() - 2;
return this.segmentIndex == lastSegmentIndex && this.segmentFraction == 1.0;
}
public boolean isVertex() {
return this.segmentFraction == 0.0 || this.segmentFraction == 1.0;
}
@Override
public String toString() {
return getPoint() + " i=" + this.segmentIndex + " %=" + this.segmentFraction * 100 + " d="
+ this.distance;
}
}