001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/io/shpapi/shape_new/ShapeMultiPoint.java $
002    /*----------------------------------------------------------------------------
003     This file is part of deegree, http://deegree.org/
004     Copyright (C) 2001-2009 by:
005       Department of Geography, University of Bonn
006     and
007       lat/lon GmbH
008    
009     This library is free software; you can redistribute it and/or modify it under
010     the terms of the GNU Lesser General Public License as published by the Free
011     Software Foundation; either version 2.1 of the License, or (at your option)
012     any later version.
013     This library is distributed in the hope that it will be useful, but WITHOUT
014     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016     details.
017     You should have received a copy of the GNU Lesser General Public License
018     along with this library; if not, write to the Free Software Foundation, Inc.,
019     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020    
021     Contact information:
022    
023     lat/lon GmbH
024     Aennchenstr. 19, 53177 Bonn
025     Germany
026     http://lat-lon.de/
027    
028     Department of Geography, University of Bonn
029     Prof. Dr. Klaus Greve
030     Postfach 1147, 53001 Bonn
031     Germany
032     http://www.geographie.uni-bonn.de/deegree/
033    
034     e-mail: info@deegree.org
035    ----------------------------------------------------------------------------*/
036    package org.deegree.io.shpapi.shape_new;
037    
038    import org.deegree.model.crs.CoordinateSystem;
039    import org.deegree.model.spatialschema.ByteUtils;
040    import org.deegree.model.spatialschema.Geometry;
041    import org.deegree.model.spatialschema.GeometryException;
042    import org.deegree.model.spatialschema.GeometryFactory;
043    import org.deegree.model.spatialschema.MultiPoint;
044    import org.deegree.model.spatialschema.Point;
045    import org.deegree.model.spatialschema.WKTAdapter;
046    
047    /**
048     * <code>ShapeMultiPoint</code> encapsulates shapefile MultiPoint/M/Z structures.
049     *
050     * @author <a href="mailto:schmitz@lat-lon.de">Andreas Schmitz</a>
051     * @author last edited by: $Author: mschneider $
052     *
053     * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
054     */
055    public class ShapeMultiPoint implements Shape {
056    
057        private CoordinateSystem crs; // optional crs for geometry
058    
059        private boolean isM, isZ;
060    
061        private ShapeEnvelope envelope;
062    
063        protected ShapePoint[] points;
064    
065        /**
066         * @param isZ
067         * @param isM
068         */
069        public ShapeMultiPoint( boolean isZ, boolean isM ) {
070            this.isZ = isZ;
071            this.isM = isM;
072        }
073    
074        /**
075         * @param isZ
076         * @param isM
077         * @param crs
078         *            CoordinateSystem for shape
079         */
080        public ShapeMultiPoint( boolean isZ, boolean isM, CoordinateSystem crs ) {
081            this.isZ = isZ;
082            this.isM = isM;
083            this.crs = crs;
084        }
085    
086        /**
087         * Creates MultiPointZ from deegree MultiPoint
088         *
089         * @param p
090         */
091        public ShapeMultiPoint( MultiPoint p ) {
092            if ( p.getDimension() == 3 ) {
093                isZ = true;
094            }
095            envelope = new ShapeEnvelope( p.getEnvelope() );
096    
097            Point[] ps = p.getAllPoints();
098            points = new ShapePoint[ps.length];
099    
100            for ( int i = 0; i < ps.length; ++i ) {
101                points[i] = new ShapePoint( ps[i] );
102            }
103        }
104    
105        /*
106         * (non-Javadoc)
107         *
108         * @see org.deegree.io.shpapi.Shape#getByteLength()
109         */
110        public int getByteLength() {
111            int len = 44 + points.length * 16;
112            if ( isZ ) {
113                len += 32 + points.length * 16;
114            }
115            if ( isM ) {
116                len += 16 + points.length * 8;
117            }
118            return len;
119        }
120    
121        private int readMultiPoint( byte[] bytes, int offset ) {
122            int off = offset;
123            envelope = new ShapeEnvelope( false, false );
124            off = envelope.read( bytes, off );
125    
126            int numPoints = ByteUtils.readLEInt( bytes, off );
127            off += 4;
128    
129            points = new ShapePoint[numPoints];
130    
131            for ( int i = 0; i < numPoints; ++i ) {
132                points[i] = new ShapePoint( bytes, off );
133                off += 16;
134            }
135    
136            return off;
137        }
138    
139        private int readMultiPointZ( byte[] bytes, int offset ) {
140            int off = readMultiPoint( bytes, offset );
141    
142            double zmin, zmax;
143    
144            zmin = ByteUtils.readLEDouble( bytes, off );
145            off += 8;
146            zmax = ByteUtils.readLEDouble( bytes, off );
147            off += 8;
148    
149            double[] zVals = new double[points.length];
150            for ( int i = 0; i < points.length; ++i ) {
151                zVals[i] = ByteUtils.readLEDouble( bytes, off );
152                off += 8;
153            }
154    
155            double mmin, mmax;
156    
157            mmin = ByteUtils.readLEDouble( bytes, off );
158            off += 8;
159            mmax = ByteUtils.readLEDouble( bytes, off );
160            off += 8;
161    
162            double[] mVals = new double[points.length];
163            for ( int i = 0; i < points.length; ++i ) {
164                mVals[i] = ByteUtils.readLEDouble( bytes, off );
165                off += 8;
166            }
167    
168            envelope.extend( zmin, zmax, mmin, mmax );
169    
170            for ( int i = 0; i < points.length; ++i ) {
171                points[i].extend( zVals[i], mVals[i] );
172            }
173    
174            return off;
175        }
176    
177        private int readMultiPointM( byte[] bytes, int offset ) {
178            int off = readMultiPoint( bytes, offset );
179    
180            double mmin, mmax;
181    
182            mmin = ByteUtils.readLEDouble( bytes, off );
183            off += 8;
184            mmax = ByteUtils.readLEDouble( bytes, off );
185            off += 8;
186    
187            envelope.extend( mmin, mmax );
188    
189            double m;
190            for ( int i = 0; i < points.length; ++i ) {
191                m = ByteUtils.readLEDouble( bytes, off );
192                off += 8;
193                points[i].extend( m );
194            }
195    
196            return off;
197        }
198    
199        /*
200         * (non-Javadoc)
201         *
202         * @see org.deegree.io.shpapi.Shape#read(byte[], int)
203         */
204        public int read( byte[] bytes, int offset ) {
205            int t = ByteUtils.readLEInt( bytes, offset );
206            int off = offset + 4;
207    
208            if ( t == ShapeFile.NULL ) {
209                return off;
210            }
211    
212            if ( t == ShapeFile.MULTIPOINTZ ) {
213                return readMultiPointZ( bytes, off );
214            }
215    
216            if ( t == ShapeFile.MULTIPOINTM ) {
217                return readMultiPointM( bytes, off );
218            }
219    
220            if ( t == ShapeFile.MULTIPOINT ) {
221                return readMultiPoint( bytes, off );
222            }
223    
224            return -1;
225        }
226    
227        private int writeMultiPoint( byte[] bytes, int offset ) {
228            int off = envelope.write( bytes, offset );
229    
230            ByteUtils.writeLEInt( bytes, off, points.length );
231            off += 4;
232    
233            for ( int i = 0; i < points.length; ++i ) {
234                ByteUtils.writeLEDouble( bytes, off, points[i].x );
235                off += 8;
236                ByteUtils.writeLEDouble( bytes, off, points[i].y );
237                off += 8;
238            }
239    
240            return off;
241        }
242    
243        private int writeMultiPointZ( byte[] bytes, int offset ) {
244            int off = writeMultiPoint( bytes, offset );
245    
246            ByteUtils.writeLEDouble( bytes, off, envelope.zmin );
247            off += 8;
248            ByteUtils.writeLEDouble( bytes, off, envelope.zmax );
249            off += 8;
250    
251            for ( int i = 0; i < points.length; ++i ) {
252                ByteUtils.writeLEDouble( bytes, off, points[i].z );
253                off += 8;
254            }
255    
256            ByteUtils.writeLEDouble( bytes, off, envelope.mmin );
257            off += 8;
258            ByteUtils.writeLEDouble( bytes, off, envelope.mmax );
259            off += 8;
260    
261            for ( int i = 0; i < points.length; ++i ) {
262                ByteUtils.writeLEDouble( bytes, off, points[i].m );
263                off += 8;
264            }
265    
266            return off;
267        }
268    
269        private int writeMultiPointM( byte[] bytes, int offset ) {
270            int off = writeMultiPoint( bytes, offset );
271    
272            ByteUtils.writeLEDouble( bytes, off, envelope.mmin );
273            off += 8;
274            ByteUtils.writeLEDouble( bytes, off, envelope.mmax );
275            off += 8;
276    
277            for ( int i = 0; i < points.length; ++i ) {
278                ByteUtils.writeLEDouble( bytes, off, points[i].m );
279                off += 8;
280            }
281    
282            return off;
283        }
284    
285        /*
286         * (non-Javadoc)
287         *
288         * @see org.deegree.io.shpapi.Shape#write(byte[], int)
289         */
290        public int write( byte[] bytes, int offset ) {
291            if ( isZ ) {
292                ByteUtils.writeLEInt( bytes, offset, ShapeFile.MULTIPOINTZ );
293                return writeMultiPointZ( bytes, offset + 4 );
294            }
295            if ( isM ) {
296                ByteUtils.writeLEInt( bytes, offset, ShapeFile.MULTIPOINTM );
297                return writeMultiPointM( bytes, offset + 4 );
298            }
299            ByteUtils.writeLEInt( bytes, offset, ShapeFile.MULTIPOINT );
300            return writeMultiPoint( bytes, offset + 4 );
301        }
302    
303        /*
304         * (non-Javadoc)
305         *
306         * @see org.deegree.io.shpapi.shape_new.Shape#getType()
307         */
308        public int getType() {
309            if ( isZ ) {
310                return ShapeFile.MULTIPOINTZ;
311            }
312            if ( isM ) {
313                return ShapeFile.MULTIPOINTM;
314            }
315            return ShapeFile.MULTIPOINT;
316        }
317    
318        /*
319         * (non-Javadoc)
320         *
321         * @see org.deegree.io.shpapi.shape_new.Shape#getEnvelope()
322         */
323        public ShapeEnvelope getEnvelope() {
324            return envelope;
325        }
326    
327        /**
328         * This creates a MultiPoint object.
329         *
330         * @see org.deegree.io.shpapi.shape_new.Shape#getGeometry()
331         */
332        public Geometry getGeometry()
333                                throws ShapeGeometryException {
334            if ( points == null ) {
335                return null;
336            }
337            Point[] ps = new Point[points.length];
338    
339            for ( int i = 0; i < ps.length; ++i ) {
340                ps[i] = (Point) points[i].getGeometry();
341            }
342    
343            return GeometryFactory.createMultiPoint( ps, crs );
344        }
345    
346        @Override
347        public String toString() {
348            try {
349                return WKTAdapter.export( getGeometry() ).toString();
350            } catch ( GeometryException e ) {
351                return "(unknown)";
352            }
353        }
354    
355    }