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