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