Package org.locationtech.udig.tools.geometry.split

Source Code of org.locationtech.udig.tools.geometry.split.LineBoundaryIntersectionAssociation$IntersectionLink

/* uDig - User Friendly Desktop Internet GIS
* http://udig.refractions.net
* (c) 2010, Vienna City
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* (http://www.eclipse.org/legal/epl-v10.html), and the Axios BSD
* License v1.0 (http://udig.refractions.net/files/asd3-v10.html).
*/
package org.locationtech.udig.tools.geometry.split;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.operation.distance.DistanceOp;

import org.locationtech.udig.tools.geometry.internal.util.GeometryList;

/**
* Maintains the line's segments and its intersection with the piece of boundary (exterior ring or
* interior ring).
* <p>
* The list of intersection points are ordered by the distance from the intersection point to the
* first vertex of line. The order is min distance to max distance.
* </p>
*
* <pre>
* Thus if the segment has the following intersections in the list:
* i1, i2, ...in
*
* The list is sorted using the criteria:
*
* distance(fv,i1) < distance(fv,i2)
*
* where fv is the first vertex of linestring.
* </pre>
*
* </p>
* <p>
* The intersection association between split line segment and boundary segment is:
* </p>
* <p>
* Split Line Segment (0 n)----intersect---- (0..n) Boundary Ring Segment
* </p>
*
* @author Mauricio Pazos (www.axios.es)
* @author Aritz Davila (www.axios.es)
* @since 1.3.2
*/
final class LineBoundaryIntersectionAssociation {

    private class IntersectionLink {

        private final LineString splitLineSegment;
        private final LineString ringSegment;
        private final Point intersection;

        public IntersectionLink( final LineString splitSegment, final LineString ringSegment,
                final Point intersection ) {

            assert splitSegment != null && ringSegment != null && intersection != null;

            this.splitLineSegment = splitSegment;
            this.ringSegment = ringSegment;
            this.intersection = intersection;
        }

        public String toString() {

            return "IntersectionLink( SplitLine: " + this.splitLineSegment + " - RingSegment: " + this.ringSegment + " - Intersection: " + this.intersection + ")"; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
        }

        public LineString getRingSegment() {
            return this.ringSegment;
        }

        public Point getIntersection() {
            return this.intersection;
        }
    }

    /**
     * Maintains the current intersection. It assures that the intersection between the split
     * segment and the ring segment is consistent.
     *
     * @author Mauricio Pazos (www.axios.es)
     * @author Aritz Davila (www.axios.es)
     * @since 1.3.2
     */
    public static class IntersectCursor implements Cloneable{

        private Point intersectionPoint = null;
        private int segmentPosition = -1;
        private LineString ringSegment = null;
        private int visitedIntersection = 0;


        public static IntersectCursor NULL = new IntersectCursor();

        public IntersectCursor() {
        }

        public void setCurrentIntersection( final int i, final Point intersectionPoint,
                final LineString ringSegment ) {

            setState(i, intersectionPoint, ringSegment);
        }
        public Object clone(){
            IntersectCursor duplicated = null;
            try {
               
                duplicated = (IntersectCursor)super.clone();
                duplicated.intersectionPoint = (Point) this.intersectionPoint.clone();
                duplicated.ringSegment = (LineString) this.ringSegment.clone();
                duplicated.segmentPosition = this.segmentPosition;
                duplicated.visitedIntersection = this.visitedIntersection;
               
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return duplicated;
        }
       
        public int getVisitedIntersection() {
            return this.visitedIntersection;
        }

        @Override
        public boolean equals( Object obj ) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            IntersectCursor other = (IntersectCursor) obj;
            if (intersectionPoint == null) {
                if (other.intersectionPoint != null)
                    return false;
            } else if (!intersectionPoint.equals(other.intersectionPoint))
                return false;
            if (ringSegment == null) {
                if (other.ringSegment != null)
                    return false;
            } else if (!ringSegment.equals(other.ringSegment))
                return false;
            if (segmentPosition != other.segmentPosition)
                return false;
            return true;
        }

        @Override
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime
          * result
          + ((intersectionPoint == null) ? 0 : intersectionPoint
              .hashCode());
      result = prime * result
          + ((ringSegment == null) ? 0 : ringSegment.hashCode());
      result = prime * result + segmentPosition;
      result = prime * result + visitedIntersection;
      return result;
    }


    /**
         * @return the visited intersection point
         */
        public Point getIntersectionPoint() {

            return this.intersectionPoint;
        }

        /**
         * @return the position in the segment list
         */
        public int getSegmentPosition() {
            return this.segmentPosition;
        }

        /**
         * @return the intersected ring segment by the split line segment
         */
        public LineString getIntersectedRingSegment() {
            return this.ringSegment;
        }

        private void setState( final int segmentPosition, final Point intersectionPoint,
                final LineString intersectedRingSegment ) {
            assert segmentPosition >= 0 && intersectionPoint != null
                    && intersectedRingSegment != null;

            this.segmentPosition = segmentPosition;
            this.intersectionPoint = intersectionPoint;
            this.ringSegment = intersectedRingSegment;
           
            this.visitedIntersection++;
        }

    }

    /**
     * Maintains the segment of line and intersections with the boundary
     *
     * @author Mauricio Pazos (www.axios.es)
     * @author Aritz Davila (www.axios.es)
     * @since 1.3.0
     */
    private static class SplitLineSegmentIntersectionNode {

        /** the segment of line (split line) */
        private LineString segment = null;

        /** intersection list ordered by distance from first segment's vertex. */
        private List<Point> intersectionList = null;

        private GeometryFactory geometryFactory;

        /**
         * a new instance of SegmentNode
         *
         * @param segment
         * @param intersectionList
         */
        public SplitLineSegmentIntersectionNode( final LineString segment,
                List<Point> intersectionList ) {

            this.geometryFactory = segment.getFactory();
            this.segment = segment;
            this.intersectionList = sortIntersectionByDistance(intersectionList);
        }

        public String toString() {

            StringBuilder str = new StringBuilder(this.segment.toText());
            str.append(" ["); //$NON-NLS-1$

            for( Point point : this.intersectionList ) {
                str.append(point.toText());
                str.append(" "); //$NON-NLS-1$
            }
            str.append("]"); //$NON-NLS-1$

            return str.toString();
        }

        public LineString getSegment() {

            return segment;
        }

        public List<Point> getIntersectionList() {

            return intersectionList;
        }

        /**
         * Sorts the intersection point from min to max distance of first segment's vertex
         *
         * @return a sorted list
         */
        private List<Point> sortIntersectionByDistance( final List<Point> unSortedList ) {

            if (unSortedList.size() <= 1) {
                return unSortedList;
            }
            // The unsorted list has got almost two elements. Initializes the sorted list with the
            // first
            List<Point> sortedList = new GeometryList<Point>();
            sortedList.add(0, unSortedList.get(0));

            final Point firstVertex = this.geometryFactory.createPoint(this.segment
                    .getCoordinateN(0));

            for( int i = 1; i < unSortedList.size(); i++ ) {

                Point curPoint = unSortedList.get(i);
                double newDistance = DistanceOp.distance(firstVertex, curPoint);
                assert newDistance >= 0;

                boolean wasInserted = false;
                for( int j = 0; j < sortedList.size(); j++ ) {

                    Point sortedPoint = sortedList.get(j);
                    double sortedDistance = DistanceOp.distance(firstVertex, sortedPoint);
                    assert sortedDistance >= 0;
                    if (newDistance < sortedDistance) {

                        sortedList = addPointInListFilterEquals(sortedList, j, curPoint);
                        wasInserted = true;
                        break;
                    }
                }
                if (!wasInserted) {
                    // the distance is the bigger, so add it as last element
                    if( !sortedList.contains(curPoint) ){
                        sortedList.add(curPoint);
                    }
                }
            }
            return sortedList;
        }

        /**
         * Add the intersection point taking in to account that the list must not have duplicated
         * points Note: this method was rited because the List.contains method do not work for
         * geometry element list
         *
         * @param intersectionList
         * @param insertPosition
         * @param intersectionPoint
         * @return The list with the new point (it it is not present in the list)
         */
        private List<Point> addPointInListFilterEquals( final List<Point> intersectionList,
                final int insertPosition, final Point intersectionPoint ) {

            if (intersectionList.contains(intersectionPoint)) {
                return intersectionList;
            }
            intersectionList.add(insertPosition, intersectionPoint);

            return intersectionList;
        }

        /**
         * @return the intersection nearest to the first segment's vertex.
         */
        public Point searchNearestIntersection() {

            return this.intersectionList.isEmpty() ? null : this.intersectionList.get(0);
        }

        /**
         * Searches the next intersection from the indeed point
         *
         * @param referencePoint
         * @return the next nearest intersection point
         */
        private Point searchNearestIntersectionFrom( final Point referencePoint ) {

            // found the position of reference point
            int positionOfReferencePoint = -1;
            for( int i = 0; i < this.intersectionList.size(); i++ ) {

                Point point = this.intersectionList.get(i);
                Coordinate pointCoordinate = point.getCoordinate();
                Coordinate referenceCoordinate = referencePoint.getCoordinate();
                if (pointCoordinate.equals2D(referenceCoordinate)) {
                    positionOfReferencePoint = i;
                    break;
                }
            }
            if (positionOfReferencePoint == -1) {
                return null; // not found
            }
            // It was found then return the next position, if there are a next element in the
            // intersection list
            Point nexIntersection = null;
            if ((positionOfReferencePoint + 1) < this.intersectionList.size()) {

                nexIntersection = this.intersectionList.get(positionOfReferencePoint + 1);
            }
            return nexIntersection;
        }
    } // end class SegmentNode

    /** maintains the segment position of intersection */
    private IntersectCursor                         cursor = IntersectCursor.NULL;

    /** maintains the list of split line segments an its intersection points with the ring */
    private List<SplitLineSegmentIntersectionNode>  splitLineSegmentWithIntersectionList = new LinkedList<SplitLineSegmentIntersectionNode>();

    /**
     * maintains the links between the an intersection point and the segment line and segment ring
     * which have an intersection relation
     */
    private Map<Point, IntersectionLink>            intersectionLinks = new LinkedHashMap<Point, IntersectionLink>();

    private GeometryFactory                         geomFactory;

    private IntersectCursor                         backCursor;
   

    /**
     * A new instance of {@link LineBoundaryIntersectionAssociation}
     *
     * @param lineCoords line's coordinates
     * @param ring exterior ring or an interior ring (hole) of polygon
     */
    public LineBoundaryIntersectionAssociation( final Coordinate[] lineCoords, final LinearRing ring ) {

        this.geomFactory = ring.getFactory();
        this.splitLineSegmentWithIntersectionList = makeIntersectionSegmentList(lineCoords, ring);
    }

    /**
     * Creates an array composed by the segments and its intersection points with the ring.
     *
     * @param splitLine
     * @param ring
     * @return List of segment and intersection points
     */
    private List<SplitLineSegmentIntersectionNode> makeIntersectionSegmentList(
            final Coordinate[] splitLine, final LinearRing ring ) {

        this.splitLineSegmentWithIntersectionList = new ArrayList<SplitLineSegmentIntersectionNode>();
        for( int i = 0; i < (splitLine.length - 1); i++ ) {

            LineString lineSegment = this.geomFactory.createLineString(
                    new Coordinate[]{splitLine[i], splitLine[i + 1]});

            List<Point> segmentIntersectionList = new GeometryList<Point>();
            // make the intersection between the line segment and each boundary segment in order to
            // create the intersection link
            List<LineString> ringSegmentList = ringToSegmentList(ring);
            for( LineString ringSegment : ringSegmentList ) {

                Geometry intersectionGeom = lineSegment.intersection(ringSegment);

                if (intersectionGeom instanceof Point) {

                    IntersectionLink link = new IntersectionLink(lineSegment, ringSegment,
                            (Point) intersectionGeom);
                    this.intersectionLinks.put(link.getIntersection(), link);

                    if (!segmentIntersectionList.contains(intersectionGeom)) {
                        // many ring segment could intersect in the same point with the split line,
                        // so
                        segmentIntersectionList.add((Point) intersectionGeom);
                    }
                }
            }
            SplitLineSegmentIntersectionNode lineSegmentIntersection;
            lineSegmentIntersection = new SplitLineSegmentIntersectionNode(lineSegment,
                    segmentIntersectionList);
            this.splitLineSegmentWithIntersectionList.add(lineSegmentIntersection);
        }
        return this.splitLineSegmentWithIntersectionList;
    }

    private List<LineString> ringToSegmentList( LinearRing ring ) {

        List<LineString> segmentList = new GeometryList<LineString>();

        Coordinate[] ringCoords = ring.getCoordinates();
        for( int i = 0; i < ringCoords.length - 1; i++ ) {

            LineString segment = this.geomFactory.createLineString(new Coordinate[]{ringCoords[i],
                    ringCoords[i + 1]});
            segmentList.add(segment);
        }

        return segmentList;
    }

    /**
     * Searches the first intersection in the segment list
     */
    public void moveFirstIntersection() {

        this.cursor = IntersectCursor.NULL;
        this.backCursor = this.cursor;

        for( int segmentPosition = 0; segmentPosition < this.splitLineSegmentWithIntersectionList.size(); segmentPosition++ ) {

            SplitLineSegmentIntersectionNode segmentNode = this.splitLineSegmentWithIntersectionList
                    .get(segmentPosition);
            if (!segmentNode.getIntersectionList().isEmpty()) {

                Point point = segmentNode.searchNearestIntersection();
                IntersectionLink link = this.intersectionLinks.get(point);
                LineString ringSegment = link.getRingSegment();

                this.cursor = new IntersectCursor();
                this.cursor.setCurrentIntersection(segmentPosition, point, ringSegment);

                break;
            }
        }
    }

    /**
     * The cursor is moved before the first intersection
     */
    public void moveBeforeFirst() {

        this.cursor = IntersectCursor.NULL;
    }

    /**
     * Searches the next intersection in the segment list.
     */
    public void moveNextIntersection() {

        if (this.splitLineSegmentWithIntersectionList.isEmpty()) {
            this.cursor = IntersectCursor.NULL; // there is not next
            return;
        }
        if(this.cursor == IntersectCursor.NULL){
            moveFirstIntersection();
            return;
        }
        this.backCursor = (IntersectCursor) this.cursor.clone();
       
        // the next intersection could be in the same segment or in the next segments.
        // thus the search must begin in the last visited segment.
        final int lastVisitedSegment = this.cursor.getSegmentPosition();
        final Point lastVistedIntersection = this.cursor.getIntersectionPoint();

        // search the next intersection point in the latest segment
        SplitLineSegmentIntersectionNode node = this.splitLineSegmentWithIntersectionList
                .get(lastVisitedSegment);
        Point intersectionFound = node.searchNearestIntersectionFrom(lastVistedIntersection);
        if (intersectionFound != null) {
            // found a new intersection in the last visited segment

            IntersectionLink link = this.intersectionLinks.get(intersectionFound);
            LineString ringSegment = link.getRingSegment();

            this.cursor.setCurrentIntersection(lastVisitedSegment, intersectionFound, ringSegment);

            return;
        }

        // search an intersection in the rest of segments
        for( int i = lastVisitedSegment + 1; i < this.splitLineSegmentWithIntersectionList.size(); i++ ) {

            node = this.splitLineSegmentWithIntersectionList.get(i);

            for( Point currentIntersection : node.getIntersectionList() ) {

                if ((currentIntersection != null)
                        && (!lastVistedIntersection.equals(currentIntersection))) {
                    // found an intersection in the current segment
                    IntersectionLink link = this.intersectionLinks.get(currentIntersection);
                    LineString ringSegment = link.getRingSegment();
                    this.cursor.setCurrentIntersection(i, currentIntersection, ringSegment);

                    return;
                }
            }
        }
        // it did not find an intersection, so reset the cursor
        this.cursor = IntersectCursor.NULL;
    }
   
    /**
     * Move the cursor to the back position.
     * Only one step backward is possible.   
     *
     */
    public void moveBackIntersection(){
      
        assert this.backCursor != IntersectCursor.NULL: "illegal state!. It could occurs if the client call this method without a previous calling to the moveNextIntersection() method "//$NON-NLS-1$
      
       this.cursor = this.backCursor;
       this.backCursor = IntersectCursor.NULL;
    }

    public LineString getRingSegment() {
        return this.cursor.getIntersectedRingSegment();
    }

    /**
     * @return the intersection coordinate found in the last find intersection operation
     */
    public Coordinate getIntersection() {
        return this.cursor.getIntersectionPoint().getCoordinate();
    }

    /**
     * @return the intersection coordinate found in the last find intersection operation
     */
    public int getIntersectionSegmentPosition() {
        return this.cursor.getSegmentPosition();
    }

    /**
     * @return the count of intersection between the line and the boundary
     */
    public int countIntersections() {

        List<Point> intersectionList = new GeometryList<Point>();
        for( SplitLineSegmentIntersectionNode lineIntersection : this.splitLineSegmentWithIntersectionList ) {

            for( Point point : lineIntersection.getIntersectionList() ) {

                if (!intersectionList.contains(point)) {
                    intersectionList.add(point);
                }
            }
        }
        return intersectionList.size();
    }
   
    public int getVisitedIntersection(){
        return this.cursor.getVisitedIntersection();
    }

    /**
     * Build a LineString between the the intersection of the first and the second segment.
     *
     *
     * @param firstSegmentPosition
     * @param firstIntersection
     * @param lastSegmentPosition
     * @param secondRingSegment
     * @return a LineString
     */
    public LineString buildLineBetweenIntersection(
            final int firstSegmentPosition,
            final Coordinate firstIntersection,
            final int lastSegmentPosition,
            final Coordinate secondIntersection ) {

        List<Coordinate> coordinates = new ArrayList<Coordinate>();

        // add the first intersection as first vertex
        coordinates.add(firstIntersection);

        // extract the interior vertex from the interior segments (it uses the first vertex)
        SplitLineSegmentIntersectionNode node = this.splitLineSegmentWithIntersectionList
                .get(firstSegmentPosition);
        assert lastSegmentPosition < this.splitLineSegmentWithIntersectionList.size();
       
        for( int i = firstSegmentPosition; i <= lastSegmentPosition; i++ ) {

            node = this.splitLineSegmentWithIntersectionList.get(i);
           
            Coordinate[] vertexList = node.getSegment().getCoordinates();
            for( int j = 0; j < vertexList.length; j++ ) {

                Coordinate curVertex = vertexList[j];
                if( coordinates.get(0).distance(curVertex< coordinates.get(0).distance(secondIntersection)) { 
                    // the distance of the current vertex is contained in the segment length
                    if (!coordinates.contains(curVertex)) {
                        coordinates.add(curVertex);
                    }
                }
            }
        }
        // add the intersection associated to the last segment has last vertex
        if (!coordinates.contains(secondIntersection)) {
            coordinates.add(secondIntersection );
        }

        // build the line string
        Coordinate[] coordsArray = coordinates.toArray(new Coordinate[coordinates.size()]);
        LineString newLine = this.geomFactory.createLineString(coordsArray);

        return newLine;
    }
   
    /**
     * Builds a split line fragment using the position of specified segments.
     *
     * @param firstSegmentPosition
     * @param lastSegmentPosition
     * @return an split line fragment between the first and last segment (both included)
     */
    public LineString buildLineBetweenIntersectionSegments(
            final int firstSegmentPosition,
            final int lastSegmentPosition ) {
       
        List<Coordinate> coordinatList = new LinkedList<Coordinate>();

        // extract the interior vertex from the interior segments (it uses the first vertex)
        assert (firstSegmentPosition <= lastSegmentPosition) && (lastSegmentPosition < this.splitLineSegmentWithIntersectionList.size());
       
        for( int i = firstSegmentPosition; i <= lastSegmentPosition; i++ ) {

            SplitLineSegmentIntersectionNode node = this.splitLineSegmentWithIntersectionList.get(i);
           
            Coordinate[] vertexList = node.getSegment().getCoordinates();
            for( int j = 0; j < vertexList.length; j++ ) {
                if (!coordinatList.contains(vertexList[j])) {
                    coordinatList.add(vertexList[j]);
                }
            }
        }
        // build the line string
        Coordinate[] coordinates = coordinatList.toArray(new Coordinate[coordinatList.size()]);
        LineString splitLineFragment = this.geomFactory.createLineString(coordinates);

        return splitLineFragment;
    }

    public LineString buildLineBetweenIntersectionPoints(
            final int firstSegmentPosition, final Coordinate firstIntersection,
            final int lastSegmentPosition, final Coordinate lastIntersection ) {
       
        assert (firstSegmentPosition <= lastSegmentPosition) && (lastSegmentPosition < this.splitLineSegmentWithIntersectionList.size());
       
        List<Coordinate> coordinatList = new LinkedList<Coordinate>();

        if(firstSegmentPosition == lastSegmentPosition ){
            // both intersections belong to the same line segment, then truncate the segment between the intersections point
     
            List<Coordinate> lineFragment = truncateSegmentBetween(firstSegmentPosition, firstIntersection, lastIntersection);
            coordinatList.addAll(lineFragment);
           
        } else {
            // Truncates the header of first segment using the first intersection has first vertex,
            // Insert the coordinates of intermediate line fragment
            // The last segment is truncated from the last intersection vertex
            List<Coordinate> firstLineFragment = trunkateHeaderSegment(firstSegmentPosition, firstIntersection);
            coordinatList.addAll(firstLineFragment);
           
            for( int i = firstSegmentPosition + 1; i < lastSegmentPosition; i++ ) {
   
                SplitLineSegmentIntersectionNode node = this.splitLineSegmentWithIntersectionList.get(i);
               
                Coordinate[] vertexList = node.getSegment().getCoordinates();
                for( int j = 0; j < vertexList.length; j++ ) {
                    if (!coordinatList.contains(vertexList[j])) {
                        coordinatList.add(vertexList[j]);
                    }
                }
            }
            // adds the coordinates of last segment
            List<Coordinate> lastLineFragment = trunkateTailSegment(lastSegmentPosition, lastIntersection);
            for( Coordinate coordinate : lastLineFragment ) {
                if (!coordinatList.contains(coordinate)) {
                    coordinatList.add(coordinate);
                }
            }
        }
       
        // build the line string
        Coordinate[] coordinates = coordinatList.toArray(new Coordinate[coordinatList.size()]);
        LineString splitLineFragment = this.geomFactory.createLineString(coordinates);

        return splitLineFragment;
    }
   

    /**
     * Removes the coordinates before the first intersection and after the last intersection.
     * @param firstSegmentPosition Segment to truncate
     * @param firstIntersection
     * @param lastIntersection
     * @return a truncated line fragment based in the indeed segment
     */
    private List<Coordinate> truncateSegmentBetween(
            final int           firstSegmentPosition,
            final Coordinate    firstIntersection,
            final Coordinate    lastIntersection ) {

        List<Coordinate> newLine = new LinkedList<Coordinate>();
       
        SplitLineSegmentIntersectionNode node = this.splitLineSegmentWithIntersectionList.get(firstSegmentPosition);
       
        Coordinate[] lineFragment = node.getSegment().getCoordinates();

        final double firstIntersectDistance = lineFragment[0].distance(firstIntersection);
        final double lastIntersectDistance = lineFragment[0].distance(lastIntersection);
       
        newLine.add(firstIntersection);
        for( int i = 0; i < lineFragment.length; i++ ) {
           
            // searches the position of new coordinate
            double currentDistance = lineFragment[0].distance(lineFragment[i]);
            if((firstIntersectDistance < currentDistance) && (currentDistance < lastIntersectDistance) ){
                newLine.add(lineFragment[i]);
            }
        }
        newLine.add(lastIntersection);

        return newLine;
    }

    /**
     * Makes a line fragment using the first intersection has initial vertex of the new segment.
     *
     * @param firstSegmentPosition
     * @param firstIntersection
     * @return a new line fragment that have the intersection coordinate has first vertex
     */
    private List<Coordinate> trunkateHeaderSegment( final int firstSegmentPosition, final Coordinate firstIntersection ) {

        List<Coordinate> newLine = new LinkedList<Coordinate>();
       
        SplitLineSegmentIntersectionNode node = this.splitLineSegmentWithIntersectionList.get(firstSegmentPosition);
       
        Coordinate[] lineFragment = node.getSegment().getCoordinates();
        final double vertexDistance = lineFragment[0].distance(firstIntersection);
       
        int found = -1;
        for( int i = 0; i < lineFragment.length; i++ ) {
           
            // searches the position of new coordinate
            double currentDistance = lineFragment[0].distance(lineFragment[i]);
            if(currentDistance > vertexDistance ){
                found = i;
                break;
            }
        }
        if(found != -1){
            // add the vertex and the rest of coordinates in the new segment
            newLine.add(firstIntersection);
            for(int i = found; i < lineFragment.length; i++ ){
                newLine.add(lineFragment[i]);
            }
           
        } else {
            // vertex is the last coordinate
            newLine.add(firstIntersection);
        }
        return newLine;
    }


    /**
     * Makes a new line that is cut from the last intersection
     *
     * @param lastSegmentPosition
     * @param lastIntersection
     * @return a new line as a list of coordinate
     */
    private List<Coordinate> trunkateTailSegment(
            final int lastSegmentPosition,
            final Coordinate lastIntersection ) {
       
        List<Coordinate> newLine = new LinkedList<Coordinate>();
       
        SplitLineSegmentIntersectionNode node = this.splitLineSegmentWithIntersectionList.get(lastSegmentPosition);
       
        Coordinate[] lineFragment = node.getSegment().getCoordinates();
        final double vertexDistance = lineFragment[0].distance(lastIntersection);
       
        int found = -1;
        for( int i = 0; i < lineFragment.length; i++ ) {
           
            // searches the position of new coordinate
            double currentDistance = lineFragment[0].distance(lineFragment[i]);
            if(currentDistance < vertexDistance ){
                newLine.add(lineFragment[i]);
            } else {
                found = i;
                break;
            }
        }
        if(found != -1){
            // add the vertex and the rest of coordinates in the new segment
            newLine.add(lastIntersection);
           
        } else {
            // vertex is the last coordinate
            newLine.add(lastIntersection);
        }
        return newLine;
    }
    /**
     * Returns the segment in the specified position.
     *
     * @param position
     * @return the segment of split line correspondent to the position
     */
    public LineString getSplitLineSegment( final int segmentPosition ) {

        SplitLineSegmentIntersectionNode segmentNode =this.splitLineSegmentWithIntersectionList.get(segmentPosition);
        return segmentNode.getSegment();
    }

    /**
     *
     * @return the count of segments of split line
     */
    public int size() {
       
        return this.splitLineSegmentWithIntersectionList.size();
    }


}
TOP

Related Classes of org.locationtech.udig.tools.geometry.split.LineBoundaryIntersectionAssociation$IntersectionLink

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.