001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/io/shpapi/SHPPolygon.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.CurveSegment;
043 import org.deegree.model.spatialschema.GeometryFactory;
044 import org.deegree.model.spatialschema.Ring;
045 import org.deegree.model.spatialschema.Surface;
046
047 /**
048 * Class representig a two dimensional ESRI Polygon<BR>
049 *
050 * @version 16.08.2000
051 * @author Andreas Poth
052 */
053 public class SHPPolygon extends SHPGeometry {
054
055 /**
056 *
057 */
058 public int numRings = 0;
059
060 /**
061 *
062 */
063 public int numPoints = 0;
064
065 /**
066 *
067 */
068 public SHPPolyLine rings = null;
069
070 /**
071 * constructor: recieves a stream <BR>
072 * @param recBuf
073 */
074 public SHPPolygon( byte[] recBuf ) {
075
076 super( recBuf );
077
078 envelope = ShapeUtils.readBox( recBuf, 4 );
079
080 rings = new SHPPolyLine( recBuf );
081
082 numPoints = rings.numPoints;
083 numRings = rings.numParts;
084
085 }
086
087 /**
088 * constructor: recieves an array of arrays of Points <BR>
089 * @param surface
090 */
091 public SHPPolygon( Surface[] surface ) {
092
093 try {
094 int count = 0;
095
096 for ( int i = 0; i < surface.length; i++ ) {
097 // increment for exterior ring
098 count++;
099 // increment for inner rings
100 Ring[] rings = surface[i].getSurfaceBoundary().getInteriorRings();
101 if ( rings != null ) {
102 count += rings.length;
103 }
104 }
105
106 Curve[] curves = new Curve[count];
107
108 count = 0;
109 for ( int i = 0; i < surface.length; i++ ) {
110
111 CurveSegment cs = surface[i].getSurfaceBoundary().getExteriorRing().getAsCurveSegment();
112 curves[count++] = GeometryFactory.createCurve( cs );
113
114 Ring[] rings = surface[i].getSurfaceBoundary().getInteriorRings();
115 if ( rings != null ) {
116 for ( int j = 0; j < rings.length; j++ ) {
117 cs = rings[j].getAsCurveSegment();
118 curves[count++] = GeometryFactory.createCurve( cs );
119 }
120 }
121 }
122
123 rings = new SHPPolyLine( curves );
124
125 envelope = rings.envelope;
126
127 numPoints = rings.numPoints;
128 numRings = rings.numParts;
129
130 } catch ( Exception e ) {
131 e.printStackTrace();
132 }
133
134 }
135
136 /**
137 * method: writeSHPPolygon(byte[] bytearray, int start)<BR>
138 * @param bytearray
139 * @param start
140 * @return the byte array again
141 */
142 public byte[] writeSHPPolygon( byte[] bytearray, int start ) {
143
144 int offset = start;
145
146 double xmin = rings.points[0][0].x;
147 double xmax = rings.points[0][0].x;
148 double ymin = rings.points[0][0].y;
149 double ymax = rings.points[0][0].y;
150
151 // write shape type identifier
152 ByteUtils.writeLEInt( bytearray, offset, ShapeConst.SHAPE_TYPE_POLYGON );
153
154 offset += 4;
155 // save offset of the bounding box
156 int tmp1 = offset;
157
158 // increment offset with size of the bounding box
159 offset += ( 4 * 8 );
160
161 // write numRings
162 ByteUtils.writeLEInt( bytearray, offset, numRings );
163 offset += 4;
164 // write numpoints
165 ByteUtils.writeLEInt( bytearray, offset, numPoints );
166 offset += 4;
167
168 // save offset of the list of offsets for each polyline
169 int tmp2 = offset;
170
171 // increment offset with numRings
172 offset += ( 4 * numRings );
173
174 int count = 0;
175 for ( int i = 0; i < rings.points.length; i++ ) {
176
177 // stores the index of the i'th part
178 ByteUtils.writeLEInt( bytearray, tmp2, count );
179 tmp2 += 4;
180
181 // write the points of the i'th part and calculate bounding box
182 for ( int j = 0; j < rings.points[i].length; j++ ) {
183 // number of the current point
184 count++;
185
186 // calculate bounding box
187 if ( rings.points[i][j].x > xmax ) {
188 xmax = rings.points[i][j].x;
189 } else if ( rings.points[i][j].x < xmin ) {
190 xmin = rings.points[i][j].x;
191 }
192
193 if ( rings.points[i][j].y > ymax ) {
194 ymax = rings.points[i][j].y;
195 } else if ( rings.points[i][j].y < ymin ) {
196 ymin = rings.points[i][j].y;
197 }
198
199 // write x-coordinate
200 ByteUtils.writeLEDouble( bytearray, offset, rings.points[i][j].x );
201 offset += 8;
202
203 // write y-coordinate
204 ByteUtils.writeLEDouble( bytearray, offset, rings.points[i][j].y );
205 offset += 8;
206
207 }
208
209 }
210
211 // jump back to the offset of the bounding box
212 offset = tmp1;
213
214 // write bounding box to the byte array
215 ByteUtils.writeLEDouble( bytearray, offset, xmin );
216 offset += 8;
217 ByteUtils.writeLEDouble( bytearray, offset, ymin );
218 offset += 8;
219 ByteUtils.writeLEDouble( bytearray, offset, xmax );
220 offset += 8;
221 ByteUtils.writeLEDouble( bytearray, offset, ymax );
222
223 return bytearray;
224 }
225
226 /**
227 * returns the polygon shape size in bytes<BR>
228 * @return the polygon shape size in bytes<BR>
229 */
230 public int size() {
231 return 44 + numRings * 4 + numPoints * 16;
232 }
233
234 @Override
235 public String toString() {
236
237 return "WKBPOLYGON" + " numRings: " + numRings;
238
239 }
240 }