All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opentripplanner.graph_builder.module.map.LinearIterator Maven / Gradle / Ivy

There is a newer version: 2.5.0
Show newest version
package org.opentripplanner.graph_builder.module.map;

import java.util.Iterator;

import org.locationtech.jts.geom.*;
import org.locationtech.jts.linearref.LinearLocation;

/**
 * I copied this class from JTS but made a few changes.
 * 
 * The JTS version of this class has several design decisions that don't work for me. In particular,
 * hasNext() in the original should be "isValid", and if we start mid-segment, we should continue at
 * the end of this segment rather than the end of the next segment.
 */
public class LinearIterator implements Iterable {

    private Geometry linearGeom;

    private final int numLines;

    /**
     * Invariant: currentLine <> null if the iterator is pointing at a valid coordinate
     * 
     * @throws IllegalArgumentException if linearGeom is not lineal
     */
    private LineString currentLine;

    private int componentIndex = 0;

    private int vertexIndex = 0;

    private double segmentFraction;

    /**
     * Creates an iterator initialized to the start of a linear {@link Geometry}
     * 
     * @param linear the linear geometry to iterate over
     * @throws IllegalArgumentException if linearGeom is not lineal
     */
    public LinearIterator(Geometry linear) {
        this(linear, 0, 0);
    }

    /**
     * Creates an iterator starting at a {@link LinearLocation} on a linear {@link Geometry}
     * 
     * @param linear the linear geometry to iterate over
     * @param start the location to start at
     * @throws IllegalArgumentException if linearGeom is not lineal
     */
    public LinearIterator(Geometry linear, LinearLocation start) {
        this(linear, start.getComponentIndex(), start.getSegmentIndex());
        this.segmentFraction = start.getSegmentFraction();
    }

    /**
     * Creates an iterator starting at a specified component and vertex in a linear {@link Geometry}
     * 
     * @param linearGeom the linear geometry to iterate over
     * @param componentIndex the component to start at
     * @param vertexIndex the vertex to start at
     * @throws IllegalArgumentException if linearGeom is not lineal
     */
    public LinearIterator(Geometry linearGeom, int componentIndex, int vertexIndex) {
        if (!(linearGeom instanceof Lineal))
            throw new IllegalArgumentException("Lineal geometry is required");
        this.linearGeom = linearGeom;
        numLines = linearGeom.getNumGeometries();
        this.componentIndex = componentIndex;
        this.vertexIndex = vertexIndex;
        loadCurrentLine();
    }

    private void loadCurrentLine() {
        if (componentIndex >= numLines) {
            currentLine = null;
            return;
        }
        currentLine = (LineString) linearGeom.getGeometryN(componentIndex);
    }

    /**
     * Tests whether there are any vertices left to iterator over.
     * 
     * @return true if there are more vertices to scan
     */
    public boolean hasNext() {
        if (componentIndex >= numLines)
            return false;
        if (componentIndex == numLines - 1 && vertexIndex >= currentLine.getNumPoints() - 1)
            return false;
        return true;
    }
    
    public boolean isValidIndex() {
        if (componentIndex >= numLines)
            return false;
        if (componentIndex == numLines - 1 && vertexIndex >= currentLine.getNumPoints())
            return false;
        return true;
    }

    /**
     * Moves the iterator ahead to the next vertex and (possibly) linear component.
     */
    public void next() {
        if (!hasNext())
            return;
        segmentFraction = 0.0;
        vertexIndex++;
        if (vertexIndex >= currentLine.getNumPoints()) {
            componentIndex++;
            if (componentIndex < linearGeom.getNumGeometries() - 1) {
                loadCurrentLine();
                vertexIndex = 0;
            }
        }
    }

    /**
     * Checks whether the iterator cursor is pointing to the endpoint of a linestring.
     * 
     * @return true if the iterator is at an endpoint
     */
    public boolean isEndOfLine() {
        if (componentIndex >= numLines)
            return false;
        // LineString currentLine = (LineString) linear.getGeometryN(componentIndex);
        if (vertexIndex < currentLine.getNumPoints() - 1)
            return false;
        return true;
    }

    /**
     * The component index of the vertex the iterator is currently at.
     * 
     * @return the current component index
     */
    public int getComponentIndex() {
        return componentIndex;
    }

    /**
     * The vertex index of the vertex the iterator is currently at.
     * 
     * @return the current vertex index
     */
    public int getVertexIndex() {
        return vertexIndex;
    }

    /**
     * Gets the {@link LineString} component the iterator is current at.
     * 
     * @return a linestring
     */
    public LineString getLine() {
        return currentLine;
    }

    /**
     * Gets the first {@link Coordinate} of the current segment. (the coordinate of the current
     * vertex).
     * 
     * @return a {@link Coordinate}
     */
    public Coordinate getSegmentStart() {
        return currentLine.getCoordinateN(vertexIndex);
    }

    /**
     * Gets the second {@link Coordinate} of the current segment. (the coordinate of the next
     * vertex). If the iterator is at the end of a line, null is returned.
     * 
     * @return a {@link Coordinate} or null
     */
    public Coordinate getSegmentEnd() {
        if (vertexIndex < getLine().getNumPoints() - 1)
            return currentLine.getCoordinateN(vertexIndex + 1);
        return null;
    }

    public LinearLocation getLocation() {
        return new LinearLocation(componentIndex, vertexIndex, segmentFraction);
    }

    class LinearIteratorIterator implements Iterator {

        @Override
        public boolean hasNext() {
            return LinearIterator.this.hasNext();
        }

        @Override
        public LinearLocation next() {
            LinearLocation result = getLocation();
            LinearIterator.this.next();
            return result;
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }
        
    }
    @Override
    public Iterator iterator() {
        return new LinearIteratorIterator();
    }

    public static LinearLocation getEndLocation(Geometry linear) {
        //the version in LinearLocation is broken
        
        int lastComponentIndex = linear.getNumGeometries() - 1;
        LineString lastLine = (LineString) linear.getGeometryN(lastComponentIndex);
        int lastSegmentIndex = lastLine.getNumPoints() - 1;
        return new LinearLocation(lastComponentIndex, lastSegmentIndex, 0.0);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy