001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2005-2006, Geotools Project Managment Committee (PMC)
005: * (C) 2003-2004, Julian J. Ray, All Rights Reserved
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library 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 GNU
015: * Lesser General Public License for more details.
016: */
017: package org.geotools.data.tiger;
018:
019: import java.io.BufferedReader;
020: import java.io.IOException;
021: import java.util.Hashtable;
022:
023: import com.vividsolutions.jts.geom.Coordinate;
024: import com.vividsolutions.jts.geom.CoordinateArrays;
025: import com.vividsolutions.jts.geom.CoordinateList;
026: import com.vividsolutions.jts.geom.Geometry;
027: import com.vividsolutions.jts.geom.GeometryFactory;
028: import com.vividsolutions.jts.geom.LineString;
029:
030: /**
031: * <p>
032: * Title: GeoTools2 Development
033: * </p>
034: *
035: * <p>
036: * Description:
037: * </p>
038: *
039: * <p>
040: * Copyright: Copyright (c) 2003
041: * </p>
042: *
043: * <p>
044: * Company:
045: * </p>
046: *
047: * @author Julian J. Ray
048: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/unsupported/tiger/src/main/java/org/geotools/data/tiger/TigerGeometryAdapter.java $
049: * @version 1.0
050: */
051: public class TigerGeometryAdapter {
052: // Used to construct JTS geometry objects
053:
054: /** DOCUMENT ME! */
055: private final double SCALE_FACTOR = 1000000.0;
056:
057: /** DOCUMENT ME! */
058: private GeometryFactory geometryFactory;
059:
060: /** DOCUMENT ME! */
061: private BufferedReader rt2Reader;
062:
063: /** DOCUMENT ME! */
064: private int currentRow; // We perform forward-only processing on the records
065:
066: /** DOCUMENT ME! */
067: private Hashtable type2s;
068:
069: // Used to test for NULL geometries read from the RT2 file
070:
071: /** DOCUMENT ME! */
072: private Coordinate nullCoord = new Coordinate(0.0, 0.0);
073:
074: /**
075: * TigerGeometryAdapter
076: *
077: * @param rt2Reader BufferedReader
078: */
079: public TigerGeometryAdapter(BufferedReader rt2Reader) {
080: // cache the reference to the reader.
081: this .rt2Reader = rt2Reader;
082:
083: // Initialize the storage
084: try {
085: type2s = new Hashtable();
086: currentRow = -1;
087: loadType2Recs();
088: } catch (IOException e) {
089: // Swallowed !
090: }
091:
092: // We cache a JTS geometry factory for expediency
093: geometryFactory = new GeometryFactory();
094: }
095:
096: /**
097: * deSerialize
098: *
099: * @param featureId String
100: * @param line String
101: *
102: * @return Geometry
103: */
104: public Geometry deSerialize(String featureId, String line) {
105: CoordinateList list = new CoordinateList();
106:
107: // Extract the shape points from the type 1 record
108: double x1 = Double.parseDouble(line.substring(190, 200));
109: double y1 = Double.parseDouble(line.substring(200, 209));
110: double xn = Double.parseDouble(line.substring(209, 219));
111: double yn = Double.parseDouble(line.substring(219, 228));
112:
113: // Add the first element
114: list.add(new Coordinate(x1 / SCALE_FACTOR, y1 / SCALE_FACTOR));
115:
116: // Look for Type2 records
117: String buff = null;
118: int i = 1;
119: Type2Record rec = new Type2Record();
120: rec.mTlid = Integer.parseInt(featureId);
121:
122: while (true) {
123: rec.Ordinal = i;
124: buff = (String) type2s.get(rec.getKey());
125:
126: if (buff != null) {
127: getCoordinates(buff, list);
128: i++;
129: } else {
130: break;
131: }
132: }
133:
134: // Add the last element
135: list.add(new Coordinate(xn / SCALE_FACTOR, yn / SCALE_FACTOR));
136:
137: // return the geometry
138: return geometryFactory.createLineString(list
139: .toCoordinateArray());
140: }
141:
142: /**
143: * getCoordinates
144: *
145: * @param buff String
146: * @param list CoordinateList
147: */
148: private void getCoordinates(String buff, CoordinateList list) {
149: Coordinate c;
150: int startPos = 18;
151: int increment = 19;
152:
153: for (int i = 0; i < 10; i++) {
154: // Extract the shape points from the type 2 record
155: double x = Double.parseDouble(buff.substring(startPos,
156: startPos + 10).trim());
157: double y = Double.parseDouble(buff.substring(startPos + 10,
158: startPos + 19).trim());
159: c = new Coordinate(x / SCALE_FACTOR, y / SCALE_FACTOR);
160:
161: // If the coords are 0.0, 0.0 then we have completed processing this feature
162: if (nullCoord.equals2D(c)) {
163: break;
164: } else {
165: list.add(c);
166: }
167:
168: startPos += increment;
169: }
170: }
171:
172: /**
173: * Constructs and returns a JTS LineString geometry.
174: *
175: * @param elems double[]
176: *
177: * @return LineString
178: */
179: private LineString createLineString(double[] elems) {
180: CoordinateList list = new CoordinateList();
181:
182: // Check to see if the elems list is long enough
183: if ((elems.length != 0) && (elems.length < 4)) {
184: return null;
185: }
186:
187: // Watch for incorrectly encoded string from the server
188: if ((elems.length % 2) != 0) {
189: return null;
190: }
191:
192: for (int i = 0; i < elems.length;) {
193: list.add(new Coordinate(elems[i], elems[i + 1]));
194: i += 2;
195: }
196:
197: return geometryFactory.createLineString(CoordinateArrays
198: .toCoordinateArray(list));
199: }
200:
201: /**
202: * loadType2Recs - read the type twos and sort them on non-deacresing tlid and ordinal
203: *
204: * @throws IOException
205: */
206: private void loadType2Recs() throws IOException {
207: String buffer;
208:
209: while (true) {
210: buffer = rt2Reader.readLine();
211:
212: if (buffer == null) {
213: break;
214: }
215:
216: Type2Record rec = new Type2Record();
217: rec.mTlid = Integer
218: .parseInt(buffer.substring(5, 15).trim());
219: rec.Ordinal = Integer.parseInt(buffer.substring(15, 18)
220: .trim());
221:
222: // Add it to the cache
223: type2s.put(rec.getKey(), buffer);
224: }
225: }
226:
227: /**
228: * <p>
229: * Title: GeoTools2 Development
230: * </p>
231: *
232: * <p>
233: * Description:
234: * </p>
235: *
236: * <p>
237: * Copyright: Copyright (c) 2003
238: * </p>
239: *
240: * <p>
241: * Company:
242: * </p>
243: *
244: * @author Julian J. Ray
245: * @version 1.0
246: */
247: private class Type2Record {
248: //~ Instance fields --------------------------------------------------------------------------------------------
249:
250: /** DOCUMENT ME! */
251: int mTlid;
252:
253: /** DOCUMENT ME! */
254: int Ordinal;
255:
256: //~ Methods ----------------------------------------------------------------------------------------------------
257:
258: /**
259: * DOCUMENT ME!
260: *
261: * @return DOCUMENT ME!
262: */
263: public Integer getKey() {
264: return new Integer((mTlid * 100) + Ordinal);
265: }
266: }
267: }
|