Class NodedSegmentString

  1  
  2 /*
  3  * Copyright (c) 2016 Vivid Solutions.
  4  *
  5  * All rights reserved. This program and the accompanying materials
  6  * are made available under the terms of the Eclipse Public License 2.0
  7  * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
  8  * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
  9  * and the Eclipse Distribution License is available at
 10  *
 11  * http://www.eclipse.org/org/documents/edl-v10.php.
 12  */
 13 package org.locationtech.jts.noding;
 14  
 15 import java.util.ArrayList;
 16 import java.util.Collection;
 17 import java.util.Iterator;
 18 import java.util.List;
 19  
 20 import org.locationtech.jts.algorithm.LineIntersector;
 21 import org.locationtech.jts.geom.Coordinate;
 22 import org.locationtech.jts.geom.impl.CoordinateArraySequence;
 23 import org.locationtech.jts.io.WKTWriter;
 24  
 25 /**
 26  * Represents a list of contiguous line segments,
 27  * and supports noding the segments.
 28  * The line segments are represented by an array of {@link Coordinate}s.
 29  * Intended to optimize the noding of contiguous segments by
 30  * reducing the number of allocated objects.
 31  * SegmentStrings can carry a context object, which is useful
 32  * for preserving topological or parentage information.
 33  * All noded substrings are initialized with the same context object.
 34  *
 35  * @version 1.7
 36  */
 37 public class NodedSegmentString
 38     implements NodableSegmentString
 39 {
 40     /**
 41      * Gets the {@link SegmentString}s which result from splitting this string at node points.
 42      * 
 43      * @param segStrings a Collection of NodedSegmentStrings
 44      * @return a Collection of NodedSegmentStrings representing the substrings
 45      */
 46   public static List getNodedSubstrings(Collection segStrings)
 47   {
 48     List resultEdgelist = new ArrayList();
 49     getNodedSubstrings(segStrings, resultEdgelist);
 50     return resultEdgelist;
 51   }
 52  
 53     /**
 54      * Adds the noded {@link SegmentString}s which result from splitting this string at node points.
 55      * 
 56      * @param segStrings a Collection of NodedSegmentStrings
 57      * @param resultEdgelist a List which will collect the NodedSegmentStrings representing the substrings
 58      */
 59  public static void getNodedSubstrings(Collection segStrings, Collection resultEdgelist)
 60   {
 61     for (Iterator i = segStrings.iterator(); i.hasNext(); ) {
 62       NodedSegmentString ss = (NodedSegmentString) i.next();
 63       ss.getNodeList().addSplitEdges(resultEdgelist);
 64     }
 65   }
 66  
 67   private SegmentNodeList nodeList = new SegmentNodeList(this);
 68   private Coordinate[] pts;
 69   private Object data;
 70  
 71   /**
 72    * Creates a new segment string from a list of vertices.
 73    *
 74    * @param pts the vertices of the segment string
 75    * @param data the user-defined data of this segment string (may be null)
 76    */
 77   public NodedSegmentString(Coordinate[] pts, Object data)
 78   {
 79     this.pts = pts;
 80     this.data = data;
 81   }
 82  
 83   /**
 84    * Gets the user-defined data for this segment string.
 85    *
 86    * @return the user-defined data
 87    */
 88   public Object getData() { return data; }
 89  
 90   /**
 91    * Sets the user-defined data for this segment string.
 92    *
 93    * @param data an Object containing user-defined data
 94    */
 95   public void setData(Object data) { this.data = data; }
 96  
 97   public SegmentNodeList getNodeList() { return nodeList; }
 98   public int size() { return pts.length; }
 99   public Coordinate getCoordinate(int i) { return pts[i]; }
100   public Coordinate[] getCoordinates() { return pts; }
101  
102   public boolean isClosed()
103   {
104     return pts[0].equals(pts[pts.length - 1]);
105   }
106  
107   /**
108    * Gets the octant of the segment starting at vertex <code>index</code>.
109    *
110    * @param index the index of the vertex starting the segment.  Must not be
111    * the last index in the vertex list
112    * @return the octant of the segment at the vertex
113    */
114   public int getSegmentOctant(int index)
115   {
116     if (index == pts.length - 1return -1;
117     return safeOctant(getCoordinate(index), getCoordinate(index + 1));
118 //    return Octant.octant(getCoordinate(index), getCoordinate(index + 1));
119   }
120  
121   private int safeOctant(Coordinate p0, Coordinate p1)
122   {
123       if (p0.equals2D(p1)) return 0;
124       return Octant.octant(p0, p1);
125   }
126   
127   /**
128    * Adds EdgeIntersections for one or both
129    * intersections found for a segment of an edge to the edge intersection list.
130    */
131   public void addIntersections(LineIntersector li, int segmentIndex, int geomIndex)
132   {
133     for (int i = 0; i < li.getIntersectionNum(); i++) {
134       addIntersection(li, segmentIndex, geomIndex, i);
135     }
136   }
137   /**
138    * Add an SegmentNode for intersection intIndex.
139    * An intersection that falls exactly on a vertex
140    * of the SegmentString is normalized
141    * to use the higher of the two possible segmentIndexes
142    */
143   public void addIntersection(LineIntersector li, int segmentIndex, int geomIndex, int intIndex)
144   {
145     Coordinate intPt = new Coordinate(li.getIntersection(intIndex));
146     addIntersection(intPt, segmentIndex);
147   }
148  
149   /**
150    * Adds an intersection node for a given point and segment to this segment string.
151    * 
152    * @param intPt the location of the intersection
153    * @param segmentIndex the index of the segment containing the intersection
154    */
155   public void  addIntersection(Coordinate intPt, int segmentIndex) {
156       addIntersectionNode(intPt, segmentIndex);
157   }
158       
159   /**
160    * Adds an intersection node for a given point and segment to this segment string.
161    * If an intersection already exists for this exact location, the existing
162    * node will be returned.
163    * 
164    * @param intPt the location of the intersection
165    * @param segmentIndex the index of the segment containing the intersection
166    * @return the intersection node for the point
167    */
168   public SegmentNode addIntersectionNode(Coordinate intPt, int segmentIndex) {
169         int normalizedSegmentIndex = segmentIndex;
170         //Debug.println("edge intpt: " + intPt + " dist: " + dist);
171         // normalize the intersection point location
172         int nextSegIndex = normalizedSegmentIndex + 1;
173         if (nextSegIndex < pts.length) {
174             Coordinate nextPt = pts[nextSegIndex];
175             //Debug.println("next pt: " + nextPt);
176  
177             // Normalize segment index if intPt falls on vertex
178             // The check for point equality is 2D only - Z values are ignored
179             if (intPt.equals2D(nextPt)) {
180                 //Debug.println("normalized distance");
181                 normalizedSegmentIndex = nextSegIndex;
182             }
183         }
184         /**
185          * Add the intersection point to edge intersection list.
186          */
187         SegmentNode ei = nodeList.add(intPt, normalizedSegmentIndex);
188         return ei;
189     }
190   
191   public String toString()
192   {
193       return WKTWriter.toLineString(new CoordinateArraySequence(pts));
194   }
195 }
196