001: /*
002: * The JTS Topology Suite is a collection of Java classes that
003: * implement the fundamental operations required to validate a given
004: * geo-spatial data set to a known topological specification.
005: *
006: * Copyright (C) 2001 Vivid Solutions
007: *
008: * This library is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU Lesser General Public
010: * License as published by the Free Software Foundation; either
011: * version 2.1 of the License, or (at your option) any later version.
012: *
013: * This library is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016: * Lesser General Public License for more details.
017: *
018: * You should have received a copy of the GNU Lesser General Public
019: * License along with this library; if not, write to the Free Software
020: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021: *
022: * For more information, contact:
023: *
024: * Vivid Solutions
025: * Suite #1A
026: * 2328 Government Street
027: * Victoria BC V8T 5G5
028: * Canada
029: *
030: * (250)385-6040
031: * www.vividsolutions.com
032: */
033: package com.vividsolutions.jts.geomgraph;
034:
035: import com.vividsolutions.jts.geom.*;
036: import java.io.*;
037: import java.util.*;
038:
039: /**
040: * A list of edge intersections along an {@link Edge}.
041: * Implements splitting an edge with intersections
042: * into multiple resultant edges.
043: *
044: * @version 1.7
045: */
046: public class EdgeIntersectionList {
047: // a Map <EdgeIntersection, EdgeIntersection>
048: private Map nodeMap = new TreeMap();
049: Edge edge; // the parent edge
050:
051: public EdgeIntersectionList(Edge edge) {
052: this .edge = edge;
053: }
054:
055: /**
056: * Adds an intersection into the list, if it isn't already there.
057: * The input segmentIndex and dist are expected to be normalized.
058: * @return the EdgeIntersection found or added
059: */
060: public EdgeIntersection add(Coordinate intPt, int segmentIndex,
061: double dist) {
062: EdgeIntersection eiNew = new EdgeIntersection(intPt,
063: segmentIndex, dist);
064: EdgeIntersection ei = (EdgeIntersection) nodeMap.get(eiNew);
065: if (ei != null) {
066: return ei;
067: }
068: nodeMap.put(eiNew, eiNew);
069: return eiNew;
070: }
071:
072: /**
073: * Returns an iterator of {@link EdgeIntersection}s
074: *
075: * @return an Iterator of EdgeIntersections
076: */
077: public Iterator iterator() {
078: return nodeMap.values().iterator();
079: }
080:
081: /**
082: * Tests if the given point is an edge intersection
083: *
084: * @param pt the point to test
085: * @return true if the point is an intersection
086: */
087: public boolean isIntersection(Coordinate pt) {
088: for (Iterator it = iterator(); it.hasNext();) {
089: EdgeIntersection ei = (EdgeIntersection) it.next();
090: if (ei.coord.equals(pt))
091: return true;
092: }
093: return false;
094: }
095:
096: /**
097: * Adds entries for the first and last points of the edge to the list
098: */
099: public void addEndpoints() {
100: int maxSegIndex = edge.pts.length - 1;
101: add(edge.pts[0], 0, 0.0);
102: add(edge.pts[maxSegIndex], maxSegIndex, 0.0);
103: }
104:
105: /**
106: * Creates new edges for all the edges that the intersections in this
107: * list split the parent edge into.
108: * Adds the edges to the input list (this is so a single list
109: * can be used to accumulate all split edges for a Geometry).
110: *
111: * @param edgeList a list of EdgeIntersections
112: */
113: public void addSplitEdges(List edgeList) {
114: // ensure that the list has entries for the first and last point of the edge
115: addEndpoints();
116:
117: Iterator it = iterator();
118: // there should always be at least two entries in the list
119: EdgeIntersection eiPrev = (EdgeIntersection) it.next();
120: while (it.hasNext()) {
121: EdgeIntersection ei = (EdgeIntersection) it.next();
122: Edge newEdge = createSplitEdge(eiPrev, ei);
123: edgeList.add(newEdge);
124:
125: eiPrev = ei;
126: }
127: }
128:
129: /**
130: * Create a new "split edge" with the section of points between
131: * (and including) the two intersections.
132: * The label for the new edge is the same as the label for the parent edge.
133: */
134: Edge createSplitEdge(EdgeIntersection ei0, EdgeIntersection ei1) {
135: //Debug.print("\ncreateSplitEdge"); Debug.print(ei0); Debug.print(ei1);
136: int npts = ei1.segmentIndex - ei0.segmentIndex + 2;
137:
138: Coordinate lastSegStartPt = edge.pts[ei1.segmentIndex];
139: // if the last intersection point is not equal to the its segment start pt,
140: // add it to the points list as well.
141: // (This check is needed because the distance metric is not totally reliable!)
142: // The check for point equality is 2D only - Z values are ignored
143: boolean useIntPt1 = ei1.dist > 0.0
144: || !ei1.coord.equals2D(lastSegStartPt);
145: if (!useIntPt1) {
146: npts--;
147: }
148:
149: Coordinate[] pts = new Coordinate[npts];
150: int ipt = 0;
151: pts[ipt++] = new Coordinate(ei0.coord);
152: for (int i = ei0.segmentIndex + 1; i <= ei1.segmentIndex; i++) {
153: pts[ipt++] = edge.pts[i];
154: }
155: if (useIntPt1)
156: pts[ipt] = ei1.coord;
157: return new Edge(pts, new Label(edge.label));
158: }
159:
160: public void print(PrintStream out) {
161: out.println("Intersections:");
162: for (Iterator it = iterator(); it.hasNext();) {
163: EdgeIntersection ei = (EdgeIntersection) it.next();
164: ei.print(out);
165: }
166: }
167: }
|