001: package com.vividsolutions.jts.linearref;
002:
003: import com.vividsolutions.jts.geom.*;
004:
005: /**
006: * An iterator over the components and coordinates of a linear geometry
007: * ({@link LineString}s and {@link MultiLineString}s.
008: *
009: * The standard usage pattern for a {@link LinearIterator} is:
010: *
011: * <pre>
012: * for (LinearIterator it = new LinearIterator(...); it.hasNext(); it.next()) {
013: * ...
014: * int ci = it.getComponentIndex(); // for example
015: * int vi = it.getVertexIndex(); // for example
016: * ...
017: * }
018: * </pre>
019: *
020: * @version 1.7
021: */
022: public class LinearIterator {
023: private static int segmentEndVertexIndex(LinearLocation loc) {
024: if (loc.getSegmentFraction() > 0.0)
025: return loc.getSegmentIndex() + 1;
026: return loc.getSegmentIndex();
027: }
028:
029: private Geometry linear;
030: private final int numLines;
031:
032: /**
033: * Invariant: currentLine <> null if the iterator is pointing at a valid coordinate
034: */
035: private LineString currentLine;
036: private int componentIndex = 0;
037: private int vertexIndex = 0;
038:
039: /**
040: * Creates an iterator initialized to the start of a linear {@link Geometry}
041: *
042: * @param linear the linear geometry to iterate over
043: */
044: public LinearIterator(Geometry linear) {
045: this (linear, 0, 0);
046: }
047:
048: /**
049: * Creates an iterator starting at
050: * a {@link LinearLocation} on a linear {@link Geometry}
051: *
052: * @param linear the linear geometry to iterate over
053: * @param start the location to start at
054: */
055: public LinearIterator(Geometry linear, LinearLocation start) {
056: this (linear, start.getComponentIndex(),
057: segmentEndVertexIndex(start));
058: }
059:
060: /**
061: * Creates an iterator starting at
062: * a component and vertex in a linear {@link Geometry}
063: *
064: * @param linear the linear geometry to iterate over
065: * @param componentIndex the component to start at
066: * @param vertexIndex the vertex to start at
067: */
068: public LinearIterator(Geometry linear, int componentIndex,
069: int vertexIndex) {
070: this .linear = linear;
071: numLines = linear.getNumGeometries();
072: this .componentIndex = componentIndex;
073: this .vertexIndex = vertexIndex;
074: loadCurrentLine();
075: }
076:
077: private void loadCurrentLine() {
078: if (componentIndex >= numLines) {
079: currentLine = null;
080: return;
081: }
082: currentLine = (LineString) linear.getGeometryN(componentIndex);
083: }
084:
085: /**
086: * Tests whether there are any vertices left to iterator over.
087: * @return <code>true</code> if there are more vertices to scan
088: */
089: public boolean hasNext() {
090: if (componentIndex >= numLines)
091: return false;
092: if (componentIndex == numLines - 1
093: && vertexIndex >= currentLine.getNumPoints())
094: return false;
095: return true;
096: }
097:
098: /**
099: * Moves the iterator ahead to the next vertex and (possibly) linear component.
100: */
101: public void next() {
102: if (!hasNext())
103: return;
104:
105: vertexIndex++;
106: if (vertexIndex >= currentLine.getNumPoints()) {
107: componentIndex++;
108: loadCurrentLine();
109: vertexIndex = 0;
110: }
111: }
112:
113: /**
114: * Checks whether the iterator cursor is pointing to the
115: * endpoint of a linestring.
116: *
117: * @return <code>true</true> if the iterator is at an endpoint
118: */
119: public boolean isEndOfLine() {
120: if (componentIndex >= numLines)
121: return false;
122: //LineString currentLine = (LineString) linear.getGeometryN(componentIndex);
123: if (vertexIndex < currentLine.getNumPoints() - 1)
124: return false;
125: return true;
126: }
127:
128: /**
129: * The component index of the vertex the iterator is currently at.
130: * @return the current component index
131: */
132: public int getComponentIndex() {
133: return componentIndex;
134: }
135:
136: /**
137: * The vertex index of the vertex the iterator is currently at.
138: * @return the current vertex index
139: */
140: public int getVertexIndex() {
141: return vertexIndex;
142: }
143:
144: /**
145: * Gets the {@link LineString} component the iterator is current at.
146: * @return a linestring
147: */
148: public LineString getLine() {
149: return currentLine;
150: }
151:
152: /**
153: * Gets the first {@link Coordinate} of the current segment.
154: * (the coordinate of the current vertex).
155: * @return a {@link Coordinate}
156: */
157: public Coordinate getSegmentStart() {
158: return currentLine.getCoordinateN(vertexIndex);
159: }
160:
161: /**
162: * Gets the second {@link Coordinate} of the current segment.
163: * (the coordinate of the next vertex).
164: * If the iterator is at the end of a line, <code>null</code> is returned.
165: *
166: * @return a {@link Coordinate} or <code>null</code>
167: */
168: public Coordinate getSegmentEnd() {
169: if (vertexIndex < getLine().getNumPoints() - 1)
170: return currentLine.getCoordinateN(vertexIndex + 1);
171: return null;
172: }
173: }
|