001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_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    }