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    }