001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/io/shpapi/SHPPolyLine.java $ 002 003 /*---------------- FILE HEADER ------------------------------------------ 004 005 This file is part of deegree. 006 Copyright (C) 2001-2006 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: 6703 $, $Date: 2007-04-26 18:34:21 +0200 (Do, 26 Apr 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 }