    001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_testing/src/org/deegree/io/shpapi/SHPPolyLine.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.LineString;
    043
    044    /**
    045     * Class representig a two dimensional ESRI PolyLine<BR>
    046     *
    047     *
    048     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
    049     * @author last edited by: $Author: mschneider $
    050     *
    051     * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
    052     */
    053    public class SHPPolyLine extends SHPGeometry {
    054
    055        /**
    056         *
    057         */
    058        public int numParts;
    059
    060        /**
    061         *
    062         */
    063        public int numPoints;
    064
    065        /**
    066         *
    067         */
    068        public SHPPoint[][] points = null;
    069
    070        /**
    071         * constructor: gets a stream <BR>
    072         *
    073         * @param recBuf
    074         */
    075        public SHPPolyLine( byte[] recBuf ) {
    076
    077            // constructor invocation
    078            super( recBuf );
    079
    080            int pointsStart = 0;
    081            int sumPoints = 0;
    082
    083            envelope = ShapeUtils.readBox( recBuf, 4 );
    084
    085            numParts = ByteUtils.readLEInt( recBuffer, 36 );
    086            numPoints = ByteUtils.readLEInt( recBuffer, 40 );
    087
    088            pointsStart = ShapeConst.PARTS_START + ( numParts * 4 );
    089
    090            points = new SHPPoint[numParts][];
    091
    092            for ( int j = 0; j < numParts; j++ ) {
    093
    094                int firstPointNo = 0;
    095                int nextFirstPointNo = 0;
    096                int offset = 0;
    097                int lnumPoints = 0;
    098
    099                // get number of first point of current part out of ESRI shape Record:
    100                firstPointNo = ByteUtils.readLEInt( recBuffer, ShapeConst.PARTS_START + ( j * 4 ) );
    101
    102                // calculate offset of part in bytes, count from the beginning of recordbuffer
    103                offset = pointsStart + ( firstPointNo * 16 );
    104
    105                // get number of first point of next part ...
    106                if ( j < numParts - 1 ) {
    107                    // ... usually out of ESRI shape Record
    108                    nextFirstPointNo = ByteUtils.readLEInt( recBuffer, ShapeConst.PARTS_START + ( ( j + 1 ) * 4 ) );
    109                }
    110                // ... for the last part as total number of points
    111                else if ( j == numParts - 1 ) {
    112                    nextFirstPointNo = numPoints;
    113                }
    114
    115                // calculate number of points per part due to distance and
    116                // calculate some checksum for the total number of points to be worked
    117                lnumPoints = nextFirstPointNo - firstPointNo;
    118                sumPoints += lnumPoints;
    119
    120                // allocate memory for the j-th part
    121                points[j] = new SHPPoint[lnumPoints];
    122
    123                // create the points of the j-th part from the buffer
    124                for ( int i = 0; i < lnumPoints; i++ ) {
    125                    points[j][i] = new SHPPoint( recBuf, offset + ( i * 16 ) );
    126                }
    127
    128            }
    129
    130        }
    131
    132        /**
    133         * constructor: recieves a matrix of Points <BR>
    134         *
    135         * @param curve
    136         */
    137        public SHPPolyLine( Curve[] curve ) {
    138
    139            double xmin = curve[0].getEnvelope().getMin().getX();
    140            double xmax = curve[0].getEnvelope().getMax().getX();
    141            double ymin = curve[0].getEnvelope().getMin().getY();
    142            double ymax = curve[0].getEnvelope().getMax().getY();
    143
    144            numParts = curve.length;
    145
    146            numPoints = 0;
    147
    148            points = new SHPPoint[numParts][];
    149
    150            try {
    151                // create SHPPoints from the Points array
    152                for ( int i = 0; i < numParts; i++ ) {
    153
    154                    LineString ls = curve[i].getAsLineString();
    155
    156                    numPoints += ls.getNumberOfPoints();
    157
    158                    points[i] = new SHPPoint[ls.getNumberOfPoints()];
    159
    160                    for ( int j = 0; j < ls.getNumberOfPoints(); j++ ) {
    161                        points[i][j] = new SHPPoint( ls.getPositionAt( j ) );
    162                        if ( points[i][j].x > xmax ) {
    163                            xmax = points[i][j].x;
    164                        } else if ( points[i][j].x < xmin ) {
    165                            xmin = points[i][j].x;
    166                        }
    167                        if ( points[i][j].y > ymax ) {
    168                            ymax = points[i][j].y;
    169                        } else if ( points[i][j].y < ymin ) {
    170                            ymin = points[i][j].y;
    171                        }
    172                    }
    173
    174                }
    175            } catch ( Exception e ) {
    176                e.printStackTrace();
    177            }
    178
    179            envelope = new SHPEnvelope( xmin, xmax, ymax, ymin );
    180        }
    181
    182        /**
    183         *
    184         * @param bytearray
    185         * @param start
    186         */
    187        public void writeSHPPolyLine( byte[] bytearray, int start ) {
    188
    189            int offset = start;
    190
    191            double xmin = points[0][0].x;
    192            double xmax = points[0][0].x;
    193            double ymin = points[0][0].y;
    194            double ymax = points[0][0].y;
    195
    196            // write shape type identifier ( 3 = polyline )
    197            ByteUtils.writeLEInt( bytearray, offset, 3 );
    198
    199            offset += 4;
    200            // save offset of the bounding box
    201            int tmp1 = offset;
    202
    203            // increment offset with size of the bounding box
    204            offset += ( 4 * 8 );
    205
    206            // write numparts
    207            ByteUtils.writeLEInt( bytearray, offset, numParts );
    208            offset += 4;
    209            // write numpoints
    210            ByteUtils.writeLEInt( bytearray, offset, numPoints );
    211            offset += 4;
    212
    213            // save offset of the list of offsets for each polyline
    214            int tmp2 = offset;
    215
    216            // increment offset with numParts
    217            offset += ( 4 * numParts );
    218
    219            int count = 0;
    220            for ( int i = 0; i < points.length; i++ ) {
    221
    222                // stores the index of the i'th part
    223                ByteUtils.writeLEInt( bytearray, tmp2, count );
    224                tmp2 += 4;
    225
    226                // write the points of the i'th part and calculate bounding box
    227                for ( int j = 0; j < points[i].length; j++ ) {
    228
    229                    count++;
    230
    231                    // calculate bounding box
    232                    if ( points[i][j].x > xmax ) {
    233                        xmax = points[i][j].x;
    234                    } else if ( points[i][j].x < xmin ) {
    235                        xmin = points[i][j].x;
    236                    }
    237
    238                    if ( points[i][j].y > ymax ) {
    239                        ymax = points[i][j].y;
    240                    } else if ( points[i][j].y < ymin ) {
    241                        ymin = points[i][j].y;
    242                    }
    243
    244                    // write x-coordinate
    245                    ByteUtils.writeLEDouble( bytearray, offset, points[i][j].x );
    246                    offset += 8;
    247
    248                    // write y-coordinate
    249                    ByteUtils.writeLEDouble( bytearray, offset, points[i][j].y );
    250                    offset += 8;
    251
    252                }
    253
    254            }
    255
    256            // jump back to the offset of the bounding box
    257            offset = tmp1;
    258
    259            // write bounding box to the byte array
    260            ByteUtils.writeLEDouble( bytearray, offset, xmin );
    261            offset += 8;
    262            ByteUtils.writeLEDouble( bytearray, offset, ymin );
    263            offset += 8;
    264            ByteUtils.writeLEDouble( bytearray, offset, xmax );
    265            offset += 8;
    266            ByteUtils.writeLEDouble( bytearray, offset, ymax );
    267
    268        }
    269
    270        /**
    271         * returns the polyline shape size in bytes<BR>
    272         *
    273         * @return the polyline shape size in bytes
    274         */
    275        public int size() {
    276            return 44 + numParts * 4 + numPoints * 16;
    277        }
    278
    279    }