001: package com.vividsolutions.jump.algorithm;
002:
003: //Martin made a decision to create this duplicate of a class from JCS.
004: //[Jon Aquino 2004-10-25]
005:
006: import com.vividsolutions.jts.geom.*;
007:
008: /**
009: * Provides various ways of computing the actual value
010: * of a point a given length along a line.
011: */
012: public class LocatePoint {
013:
014: /**
015: * Computes the location of a point a given length along a {@link LineSegment}.
016: * If the length exceeds the length of the line segment the last
017: * point of the segment is returned.
018: * If the length is negative the first point
019: * of the segment is returned.
020: *
021: * @param seg the line segment
022: * @param length the length to the desired point
023: * @return the {@link Coordinate} of the desired point
024: */
025: public static Coordinate pointAlongSegment(LineSegment seg,
026: double length) {
027: return pointAlongSegment(seg.p0, seg.p1, length);
028: }
029:
030: /**
031: * Computes the location of a point a given length along a line segment.
032: * If the length exceeds the length of the line segment the last
033: * point of the segment is returned.
034: * If the length is negative the first point
035: * of the segment is returned.
036: *
037: * @param p0 the first point of the line segment
038: * @param p1 the last point of the line segment
039: * @param length the length to the desired point
040: * @return the {@link Coordinate} of the desired point
041: */
042: public static Coordinate pointAlongSegment(Coordinate p0,
043: Coordinate p1, double length) {
044: double segLen = p1.distance(p0);
045: double frac = length / segLen;
046: if (frac <= 0.0)
047: return p0;
048: if (frac >= 1.0)
049: return p1;
050:
051: double x = (p1.x - p0.x) * frac + p0.x;
052: double y = (p1.y - p0.y) * frac + p0.y;
053: return new Coordinate(x, y);
054: }
055:
056: /**
057: * Computes the location of a point a given fraction along a line segment.
058: * If the fraction exceeds 1 the last point of the segment is returned.
059: * If the fraction is negative the first point of the segment is returned.
060: *
061: * @param p0 the first point of the line segment
062: * @param p1 the last point of the line segment
063: * @param frac the fraction of the segment to the desired point
064: * @return the {@link Coordinate} of the desired point
065: */
066: public static Coordinate pointAlongSegmentByFraction(Coordinate p0,
067: Coordinate p1, double frac) {
068: if (frac <= 0.0)
069: return p0;
070: if (frac >= 1.0)
071: return p1;
072:
073: double x = (p1.x - p0.x) * frac + p0.x;
074: double y = (p1.y - p0.y) * frac + p0.y;
075: return new Coordinate(x, y);
076: }
077:
078: /**
079: * Computes the {@link Coordinate} of the point a given length
080: * along a {@link LineString}.
081: *
082: * @param line
083: * @param length
084: * @return the {@link Coordinate} of the desired point
085: */
086: public static Coordinate pointAlongLine(LineString line,
087: double length) {
088: LocatePoint loc = new LocatePoint(line, length);
089: return loc.getPoint();
090: }
091:
092: private Coordinate pt;
093: private int index;
094:
095: public LocatePoint(LineString line, double length) {
096: compute(line, length);
097: }
098:
099: private void compute(LineString line, double length) {
100: // <TODO> handle negative distances (measure from opposite end of line)
101: double totalLength = 0.0;
102: Coordinate[] coord = line.getCoordinates();
103: for (int i = 0; i < coord.length - 1; i++) {
104: Coordinate p0 = coord[i];
105: Coordinate p1 = coord[i + 1];
106: double segLen = p1.distance(p0);
107: if (totalLength + segLen > length) {
108: pt = pointAlongSegment(p0, p1, length - totalLength);
109: index = i;
110: return;
111: }
112: totalLength += segLen;
113: }
114: // distance is greater than line length
115: pt = new Coordinate(coord[coord.length - 1]);
116: index = coord.length;
117: }
118:
119: public Coordinate getPoint() {
120: return pt;
121: }
122:
123: /**
124: * Returns the index of the segment containing the computed point
125: */
126: public int getIndex() {
127: return index;
128: }
129:
130: }
|