001: /*
002: * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI
003: * for visualizing and manipulating spatial features with geometry and attributes.
004: *
005: * Copyright (C) 2003 Vivid Solutions
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: *
021: * For more information, contact:
022: *
023: * Vivid Solutions
024: * Suite #1A
025: * 2328 Government Street
026: * Victoria BC V8T 5G5
027: * Canada
028: *
029: * (250)385-6040
030: * www.vividsolutions.com
031: */
032:
033: package com.vividsolutions.jump.qa.diff;
034:
035: import java.util.*;
036: import com.vividsolutions.jts.geom.*;
037: import com.vividsolutions.jts.geom.LineSegment;
038: import com.vividsolutions.jump.util.Counter;
039: import com.vividsolutions.jump.util.CoordinateArrays;
040:
041: public class UnmatchedEdgeExtracter {
042:
043: public static LineString toLinestring(LineSegment lineseg,
044: GeometryFactory fact) {
045: Coordinate[] coords = { lineseg.p0, lineseg.p1 };
046: return fact.createLineString(coords);
047: }
048:
049: /**
050: * following should be done with anonymous inner classes for strategy
051: */
052: private boolean isDiff; // hack to control how matching is done
053: private Map lineMap = new TreeMap();
054:
055: public UnmatchedEdgeExtracter() {
056: }
057:
058: public void add(Geometry geom) {
059: // don't need to worry about orienting polygons
060: add(CoordinateArrays.toCoordinateArrays(geom, false));
061: }
062:
063: public void add(LineString line) {
064: add(line.getCoordinates());
065: }
066:
067: public void add(List coordArrays) {
068: for (Iterator i = coordArrays.iterator(); i.hasNext();) {
069: add((Coordinate[]) i.next());
070: }
071: }
072:
073: public void add(Coordinate[] coord) {
074: for (int i = 0; i < coord.length - 1; i++) {
075: LineSegment lineseg = new LineSegment(coord[i],
076: coord[i + 1]);
077: lineseg.normalize();
078:
079: Counter counter = (Counter) lineMap.get(lineseg);
080: if (counter == null) {
081: lineMap.put(lineseg, new Counter(1));
082: } else {
083: counter.increment();
084: }
085: }
086: }
087:
088: /**
089: * This function operates in two different modes depending on the value of isDiff.
090: * If isDiff is true, the function returns true if the lineseg is present
091: * at all in the map.
092: * Is isDiff is false, the function returns true if the lineseg appears more than once
093: * in the map.
094: *
095: * @param lineseg
096: * @return true if the lineseg has a match
097: */
098: public boolean isMatched(LineSegment lineseg) {
099: Counter counter = (Counter) lineMap.get(lineseg);
100: if (counter == null)
101: return false;
102: if (isDiff) {
103: return true;
104: } else {
105: if (counter.getValue() > 1)
106: return true;
107: return false;
108: }
109: }
110:
111: /**
112: * Compute a list of all subsequences of segments in the
113: * LineString line which do not appear in the map.
114: */
115: public void getDiffEdges(Geometry geom, List edgeList) {
116: getEdges(CoordinateArrays.toCoordinateArrays(geom, false),
117: true, edgeList);
118: }
119:
120: /**
121: * Compute a list of all subsequences of segments in the
122: * LineString line which appear in the line only once.
123: */
124: public void getUnmatchedEdges(Geometry geom, List edgeList) {
125: getEdges(CoordinateArrays.toCoordinateArrays(geom, false),
126: false, edgeList);
127: }
128:
129: private void getEdges(List coordArrays, boolean isDiff,
130: List edgeList) {
131: for (Iterator i = coordArrays.iterator(); i.hasNext();) {
132: getEdges((Coordinate[]) i.next(), isDiff, edgeList);
133: }
134: }
135:
136: private void getEdges(Coordinate[] coord, boolean isDiff,
137: List edgeList) {
138: this .isDiff = isDiff;
139: GeometryFactory fact = new GeometryFactory();
140: // start is the index of the start of each line segment in the list
141: int start = 0;
142: while (start < coord.length - 1) {
143: int end = getUnmatchedSequenceEnd(coord, start);
144: if (start < end) {
145: Coordinate[] edgeCoord = new Coordinate[end - start + 1];
146: int edgeIndex = 0;
147: for (int i = start; i <= end; i++) {
148: edgeCoord[edgeIndex++] = coord[i];
149: }
150: LineString edge = fact.createLineString(edgeCoord);
151: edgeList.add(edge);
152: start = end;
153: } else {
154: start++;
155: }
156: }
157: }
158:
159: /**
160: * If no sequence matches, the value returned is equal to start
161: */
162: public int getUnmatchedSequenceEnd(Coordinate[] coord, int start) {
163: LineSegment lineseg = new LineSegment();
164: int index = start;
165: // loop while segments are unmatched
166: while (index < coord.length - 1) {
167: lineseg.setCoordinates(coord[index], coord[index + 1]);
168: lineseg.normalize();
169: // if this segment is matched, exit loop
170: if (isMatched(lineseg)) {
171: break;
172: }
173: index++;
174: }
175: return index;
176: }
177: }
|