001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/io/shpapi/SHPPolyLine.java $
002
003 /*----------------------------------------------------------------------------
004 This file is part of deegree, http://deegree.org/
005 Copyright (C) 2001-2009 by:
006 Department of Geography, University of Bonn
007 and
008 lat/lon GmbH
009
010 This library is free software; you can redistribute it and/or modify it under
011 the terms of the GNU Lesser General Public License as published by the Free
012 Software Foundation; either version 2.1 of the License, or (at your option)
013 any later version.
014 This library is distributed in the hope that it will be useful, but WITHOUT
015 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
016 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
017 details.
018 You should have received a copy of the GNU Lesser General Public License
019 along with this library; if not, write to the Free Software Foundation, Inc.,
020 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021
022 Contact information:
023
024 lat/lon GmbH
025 Aennchenstr. 19, 53177 Bonn
026 Germany
027 http://lat-lon.de/
028
029 Department of Geography, University of Bonn
030 Prof. Dr. Klaus Greve
031 Postfach 1147, 53001 Bonn
032 Germany
033 http://www.geographie.uni-bonn.de/deegree/
034
035 e-mail: info@deegree.org
036 ----------------------------------------------------------------------------*/
037
038 package org.deegree.io.shpapi;
039
040 import org.deegree.model.spatialschema.ByteUtils;
041 import org.deegree.model.spatialschema.Curve;
042 import org.deegree.model.spatialschema.LineString;
043
044 /**
045 * Class representig a two dimensional ESRI PolyLine<BR>
046 *
047 *
048 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
049 * @author last edited by: $Author: mschneider $
050 *
051 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18 Jun 2009) $
052 */
053 public class SHPPolyLine extends SHPGeometry {
054
055 /**
056 *
057 */
058 public int numParts;
059
060 /**
061 *
062 */
063 public int numPoints;
064
065 /**
066 *
067 */
068 public SHPPoint[][] points = null;
069
070 /**
071 * constructor: gets a stream <BR>
072 *
073 * @param recBuf
074 */
075 public SHPPolyLine( byte[] recBuf ) {
076
077 // constructor invocation
078 super( recBuf );
079
080 int pointsStart = 0;
081 int sumPoints = 0;
082
083 envelope = ShapeUtils.readBox( recBuf, 4 );
084
085 numParts = ByteUtils.readLEInt( recBuffer, 36 );
086 numPoints = ByteUtils.readLEInt( recBuffer, 40 );
087
088 pointsStart = ShapeConst.PARTS_START + ( numParts * 4 );
089
090 points = new SHPPoint[numParts][];
091
092 for ( int j = 0; j < numParts; j++ ) {
093
094 int firstPointNo = 0;
095 int nextFirstPointNo = 0;
096 int offset = 0;
097 int lnumPoints = 0;
098
099 // get number of first point of current part out of ESRI shape Record:
100 firstPointNo = ByteUtils.readLEInt( recBuffer, ShapeConst.PARTS_START + ( j * 4 ) );
101
102 // calculate offset of part in bytes, count from the beginning of recordbuffer
103 offset = pointsStart + ( firstPointNo * 16 );
104
105 // get number of first point of next part ...
106 if ( j < numParts - 1 ) {
107 // ... usually out of ESRI shape Record
108 nextFirstPointNo = ByteUtils.readLEInt( recBuffer, ShapeConst.PARTS_START + ( ( j + 1 ) * 4 ) );
109 }
110 // ... for the last part as total number of points
111 else if ( j == numParts - 1 ) {
112 nextFirstPointNo = numPoints;
113 }
114
115 // calculate number of points per part due to distance and
116 // calculate some checksum for the total number of points to be worked
117 lnumPoints = nextFirstPointNo - firstPointNo;
118 sumPoints += lnumPoints;
119
120 // allocate memory for the j-th part
121 points[j] = new SHPPoint[lnumPoints];
122
123 // create the points of the j-th part from the buffer
124 for ( int i = 0; i < lnumPoints; i++ ) {
125 points[j][i] = new SHPPoint( recBuf, offset + ( i * 16 ) );
126 }
127
128 }
129
130 }
131
132 /**
133 * constructor: recieves a matrix of Points <BR>
134 *
135 * @param curve
136 */
137 public SHPPolyLine( Curve[] curve ) {
138
139 double xmin = curve[0].getEnvelope().getMin().getX();
140 double xmax = curve[0].getEnvelope().getMax().getX();
141 double ymin = curve[0].getEnvelope().getMin().getY();
142 double ymax = curve[0].getEnvelope().getMax().getY();
143
144 numParts = curve.length;
145
146 numPoints = 0;
147
148 points = new SHPPoint[numParts][];
149
150 try {
151 // create SHPPoints from the Points array
152 for ( int i = 0; i < numParts; i++ ) {
153
154 LineString ls = curve[i].getAsLineString();
155
156 numPoints += ls.getNumberOfPoints();
157
158 points[i] = new SHPPoint[ls.getNumberOfPoints()];
159
160 for ( int j = 0; j < ls.getNumberOfPoints(); j++ ) {
161 points[i][j] = new SHPPoint( ls.getPositionAt( j ) );
162 if ( points[i][j].x > xmax ) {
163 xmax = points[i][j].x;
164 } else if ( points[i][j].x < xmin ) {
165 xmin = points[i][j].x;
166 }
167 if ( points[i][j].y > ymax ) {
168 ymax = points[i][j].y;
169 } else if ( points[i][j].y < ymin ) {
170 ymin = points[i][j].y;
171 }
172 }
173
174 }
175 } catch ( Exception e ) {
176 e.printStackTrace();
177 }
178
179 envelope = new SHPEnvelope( xmin, xmax, ymax, ymin );
180 }
181
182 /**
183 *
184 * @param bytearray
185 * @param start
186 */
187 public void writeSHPPolyLine( byte[] bytearray, int start ) {
188
189 int offset = start;
190
191 double xmin = points[0][0].x;
192 double xmax = points[0][0].x;
193 double ymin = points[0][0].y;
194 double ymax = points[0][0].y;
195
196 // write shape type identifier ( 3 = polyline )
197 ByteUtils.writeLEInt( bytearray, offset, 3 );
198
199 offset += 4;
200 // save offset of the bounding box
201 int tmp1 = offset;
202
203 // increment offset with size of the bounding box
204 offset += ( 4 * 8 );
205
206 // write numparts
207 ByteUtils.writeLEInt( bytearray, offset, numParts );
208 offset += 4;
209 // write numpoints
210 ByteUtils.writeLEInt( bytearray, offset, numPoints );
211 offset += 4;
212
213 // save offset of the list of offsets for each polyline
214 int tmp2 = offset;
215
216 // increment offset with numParts
217 offset += ( 4 * numParts );
218
219 int count = 0;
220 for ( int i = 0; i < points.length; i++ ) {
221
222 // stores the index of the i'th part
223 ByteUtils.writeLEInt( bytearray, tmp2, count );
224 tmp2 += 4;
225
226 // write the points of the i'th part and calculate bounding box
227 for ( int j = 0; j < points[i].length; j++ ) {
228
229 count++;
230
231 // calculate bounding box
232 if ( points[i][j].x > xmax ) {
233 xmax = points[i][j].x;
234 } else if ( points[i][j].x < xmin ) {
235 xmin = points[i][j].x;
236 }
237
238 if ( points[i][j].y > ymax ) {
239 ymax = points[i][j].y;
240 } else if ( points[i][j].y < ymin ) {
241 ymin = points[i][j].y;
242 }
243
244 // write x-coordinate
245 ByteUtils.writeLEDouble( bytearray, offset, points[i][j].x );
246 offset += 8;
247
248 // write y-coordinate
249 ByteUtils.writeLEDouble( bytearray, offset, points[i][j].y );
250 offset += 8;
251
252 }
253
254 }
255
256 // jump back to the offset of the bounding box
257 offset = tmp1;
258
259 // write bounding box to the byte array
260 ByteUtils.writeLEDouble( bytearray, offset, xmin );
261 offset += 8;
262 ByteUtils.writeLEDouble( bytearray, offset, ymin );
263 offset += 8;
264 ByteUtils.writeLEDouble( bytearray, offset, xmax );
265 offset += 8;
266 ByteUtils.writeLEDouble( bytearray, offset, ymax );
267
268 }
269
270 /**
271 * returns the polyline shape size in bytes<BR>
272 *
273 * @return the polyline shape size in bytes
274 */
275 public int size() {
276 return 44 + numParts * 4 + numPoints * 16;
277 }
278
279 }