/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2001-2006 Vivid Solutions * (C) 2001-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.geometry.iso.topograph2D; import java.io.PrintStream; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.TreeMap; /** * A list of edge intersections along an {@link Edge}. Implements splitting an * edge with intersections into multiple resultant edges. * * * * @source $URL$ */ public class EdgeIntersectionList { // a Map <EdgeIntersection, EdgeIntersection> private Map nodeMap = new TreeMap(); Edge edge; // the parent edge public EdgeIntersectionList(Edge edge) { this.edge = edge; } /** * Adds an intersection into the list, if it isn't already there. The input * segmentIndex and dist are expected to be normalized. * * @return the EdgeIntersection found or added */ public EdgeIntersection add(Coordinate intPt, int segmentIndex, double dist) { EdgeIntersection eiNew = new EdgeIntersection(intPt, segmentIndex, dist); EdgeIntersection ei = (EdgeIntersection) nodeMap.get(eiNew); if (ei != null) { return ei; } nodeMap.put(eiNew, eiNew); return eiNew; } /** * Returns an iterator of {@link EdgeIntersection}s * * @return an Iterator of EdgeIntersections */ public Iterator iterator() { return nodeMap.values().iterator(); } /** * Tests if the given point is an edge intersection * * @param pt * the point to test * @return true if the point is an intersection */ public boolean isIntersection(Coordinate pt) { for (Iterator it = iterator(); it.hasNext();) { EdgeIntersection ei = (EdgeIntersection) it.next(); if (ei.coord.equals(pt)) return true; } return false; } /** * Adds entries for the first and last points of the edge to the list */ public void addEndpoints() { int maxSegIndex = edge.pts.length - 1; add(edge.pts[0], 0, 0.0); add(edge.pts[maxSegIndex], maxSegIndex, 0.0); } /** * Creates new edges for all the edges that the intersections in this list * split the parent edge into. Adds the edges to the input list (this is so * a single list can be used to accumulate all split edges for a Geometry). * * @param edgeList * a list of EdgeIntersections */ public void addSplitEdges(List edgeList) { // ensure that the list has entries for the first and last point of the // edge // e.g., add the end points of the geometry this edgeIntersectionList addEndpoints(); // Iterator of the Edge Intersections Iterator it = iterator(); // there should always be at least two entries in the list // SJ TODO The EdgeIntersection are ordered, that´s making the edge // generation easier - but how comes? where is the list of // edgeIntersections generated in ordered sequence? EdgeIntersection eiPrev = (EdgeIntersection) it.next(); while (it.hasNext()) { EdgeIntersection ei = (EdgeIntersection) it.next(); // Create new Edge from Previous EdgeIntersection to the actual // EdgeIntersection; apply the same label as the edge which inhibts // the EdgeIntersections Edge newEdge = createSplitEdge(eiPrev, ei); edgeList.add(newEdge); eiPrev = ei; } } /** * Create a new "split edge" with the section of points between (and * including) the two intersections. The label for the new edge is the same * as the label for the parent edge. */ Edge createSplitEdge(EdgeIntersection ei0, EdgeIntersection ei1) { // Debug.print("\ncreateSplitEdge"); Debug.print(ei0); Debug.print(ei1); int npts = ei1.segmentIndex - ei0.segmentIndex + 2; Coordinate lastSegStartPt = edge.pts[ei1.segmentIndex]; // if the last intersection point is not equal to the its segment start // pt, // add it to the points list as well. // (This check is needed because the distance metric is not totally // reliable!) // The check for point equality is 2D only - Z values are ignored boolean useIntPt1 = ei1.dist > 0.0 || !ei1.coord.equals2D(lastSegStartPt); if (!useIntPt1) { npts--; } Coordinate[] pts = new Coordinate[npts]; int ipt = 0; pts[ipt++] = new Coordinate(ei0.coord); for (int i = ei0.segmentIndex + 1; i <= ei1.segmentIndex; i++) { pts[ipt++] = edge.pts[i]; } if (useIntPt1) pts[ipt] = ei1.coord; return new Edge(pts, new Label(edge.label)); } public void print(PrintStream out) { out.println("Intersections:"); for (Iterator it = iterator(); it.hasNext();) { EdgeIntersection ei = (EdgeIntersection) it.next(); ei.print(out); } } }