Class EdgeIntersectionList

  1 /*
  2  * Copyright (c) 2016 Vivid Solutions.
  3  *
  4  * All rights reserved. This program and the accompanying materials
  5  * are made available under the terms of the Eclipse Public License 2.0
  6  * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
  7  * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
  8  * and the Eclipse Distribution License is available at
  9  *
 10  * http://www.eclipse.org/org/documents/edl-v10.php.
 11  */
 12 package org.locationtech.jts.geomgraph;
 13  
 14 import java.io.PrintStream;
 15 import java.util.Iterator;
 16 import java.util.List;
 17 import java.util.Map;
 18 import java.util.TreeMap;
 19  
 20 import org.locationtech.jts.geom.Coordinate;
 21  
 22 /**
 23  * A list of edge intersections along an {@link Edge}.
 24  * Implements splitting an edge with intersections
 25  * into multiple resultant edges.
 26  *
 27  * @version 1.7
 28  */
 29 public class EdgeIntersectionList
 30 {
 31   // a Map <EdgeIntersection, EdgeIntersection>
 32   private Map nodeMap = new TreeMap();
 33   Edge edge;  // the parent edge
 34  
 35   public EdgeIntersectionList(Edge edge)
 36   {
 37     this.edge = edge;
 38   }
 39  
 40   /**
 41    * Adds an intersection into the list, if it isn't already there.
 42    * The input segmentIndex and dist are expected to be normalized.
 43    * @return the EdgeIntersection found or added
 44    */
 45   public EdgeIntersection add(Coordinate intPt, int segmentIndex, double dist)
 46   {
 47     EdgeIntersection eiNew = new EdgeIntersection(intPt, segmentIndex, dist);
 48     EdgeIntersection ei = (EdgeIntersection) nodeMap.get(eiNew);
 49     if (ei != null) {
 50       return ei;
 51     }
 52     nodeMap.put(eiNew, eiNew);
 53     return eiNew;
 54   }
 55  
 56   /**
 57    * Returns an iterator of {@link EdgeIntersection}s
 58    *
 59    * @return an Iterator of EdgeIntersections
 60    */
 61   public Iterator iterator() { return nodeMap.values().iterator(); }
 62  
 63   /**
 64    * Tests if the given point is an edge intersection
 65    *
 66    * @param pt the point to test
 67    * @return true if the point is an intersection
 68    */
 69   public boolean isIntersection(Coordinate pt)
 70   {
 71     for (Iterator it = iterator(); it.hasNext(); ) {
 72       EdgeIntersection ei = (EdgeIntersection) it.next();
 73       if (ei.coord.equals(pt))
 74        return true;
 75     }
 76     return false;
 77   }
 78  
 79   /**
 80    * Adds entries for the first and last points of the edge to the list
 81    */
 82   public void addEndpoints()
 83   {
 84     int maxSegIndex = edge.pts.length - 1;
 85     add(edge.pts[0], 00.0);
 86     add(edge.pts[maxSegIndex], maxSegIndex, 0.0);
 87   }
 88  
 89   /**
 90    * Creates new edges for all the edges that the intersections in this
 91    * list split the parent edge into.
 92    * Adds the edges to the input list (this is so a single list
 93    * can be used to accumulate all split edges for a Geometry).
 94    *
 95    * @param edgeList a list of EdgeIntersections
 96    */
 97   public void addSplitEdges(List edgeList)
 98   {
 99     // ensure that the list has entries for the first and last point of the edge
100     addEndpoints();
101  
102     Iterator it = iterator();
103     // there should always be at least two entries in the list
104     EdgeIntersection eiPrev = (EdgeIntersection) it.next();
105     while (it.hasNext()) {
106       EdgeIntersection ei = (EdgeIntersection) it.next();
107       Edge newEdge = createSplitEdge(eiPrev, ei);
108       edgeList.add(newEdge);
109  
110       eiPrev = ei;
111     }
112   }
113   /**
114    * Create a new "split edge" with the section of points between
115    * (and including) the two intersections.
116    * The label for the new edge is the same as the label for the parent edge.
117    */
118   Edge createSplitEdge(EdgeIntersection ei0, EdgeIntersection ei1)
119   {
120 //Debug.print("\ncreateSplitEdge"); Debug.print(ei0); Debug.print(ei1);
121     int npts = ei1.segmentIndex - ei0.segmentIndex + 2;
122  
123     Coordinate lastSegStartPt = edge.pts[ei1.segmentIndex];
124     // if the last intersection point is not equal to the its segment start pt,
125     // add it to the points list as well.
126     // (This check is needed because the distance metric is not totally reliable!)
127     // The check for point equality is 2D only - Z values are ignored
128     boolean useIntPt1 = ei1.dist > 0.0 || ! ei1.coord.equals2D(lastSegStartPt);
129     if (! useIntPt1) {
130       npts--;
131     }
132  
133     Coordinate[] pts = new Coordinate[npts];
134     int ipt = 0;
135     pts[ipt++] = new Coordinate(ei0.coord);
136     for (int i = ei0.segmentIndex + 1; i <= ei1.segmentIndex; i++) {
137       pts[ipt++] = edge.pts[i];
138     }
139     if (useIntPt1) pts[ipt] = ei1.coord;
140     return new Edge(pts, new Label(edge.label));
141   }
142  
143   public void print(PrintStream out)
144   {
145     out.println("Intersections:");
146     for (Iterator it = iterator(); it.hasNext(); ) {
147       EdgeIntersection ei = (EdgeIntersection) it.next();
148       ei.print(out);
149     }
150   }
151 }
152