001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/io/shpapi/shape_new/ShapePoint.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.Point;
044    import org.deegree.model.spatialschema.Position;
045    import org.deegree.model.spatialschema.WKTAdapter;
046    
047    import com.vividsolutions.jts.geom.Coordinate;
048    
049    /**
050     * <code>ShapePoint</code> corresponds to Point, PointZ and PointM in shapefile terminology.
051     *
052     * @author <a href="mailto:schmitz@lat-lon.de">Andreas Schmitz</a>
053     * @author last edited by: $Author: mschneider $
054     *
055     * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
056     */
057    public class ShapePoint implements Shape {
058    
059        private CoordinateSystem crs; // optional crs for geometry
060    
061        /**
062         *
063         */
064        public boolean isZ;
065    
066        /**
067         *
068         */
069        public boolean isM;
070    
071        /**
072         * The x value.
073         */
074        public double x;
075    
076        /**
077         * The y value.
078         */
079        public double y;
080    
081        /**
082         * The z value.
083         */
084        public double z;
085    
086        /**
087         * The m value.
088         */
089        public double m;
090    
091        private boolean isNull;
092    
093        /**
094         * Constructs one without values, use read to fill it.
095         *
096         * @param z
097         *            if PointZ
098         * @param m
099         *            if PointM
100         */
101        public ShapePoint( boolean z, boolean m ) {
102            isZ = z;
103            isM = m;
104        }
105    
106        /**
107         * Constructs one without values, use read to fill it.
108         *
109         * @param z
110         *            if PointZ
111         * @param m
112         *            if PointM
113         * @param crs
114         *            CoordinateSystem of the shape
115         */
116        public ShapePoint( boolean z, boolean m, CoordinateSystem crs ) {
117            isZ = z;
118            isM = m;
119            this.crs = crs;
120        }
121    
122        /**
123         * Creates a new PointZ from deegree Point.
124         *
125         * @param p
126         */
127        public ShapePoint( Point p ) {
128            x = p.getX();
129            y = p.getY();
130            z = p.getZ();
131            if ( p.getCoordinateDimension() == 3 ) {
132                isZ = true;
133            }
134        }
135    
136        /**
137         * Creates a new PointZ from deegree Position.
138         *
139         * @param p
140         */
141        public ShapePoint( Position p ) {
142            x = p.getX();
143            y = p.getY();
144            z = p.getZ();
145            if ( p.getCoordinateDimension() == 3 ) {
146                isZ = true;
147            }
148        }
149    
150        /**
151         * Just reads x and y from the byte array.
152         *
153         * @param bytes
154         * @param offset
155         */
156        public ShapePoint( byte[] bytes, int offset ) {
157            x = ByteUtils.readLEDouble( bytes, offset );
158            y = ByteUtils.readLEDouble( bytes, offset + 8 );
159        }
160    
161        /**
162         * @return the Point as (x, y, NaN), the PointZ as (x, y, z) Coordinate
163         */
164        public Coordinate export() {
165            if ( isZ ) {
166                return new Coordinate( x, y, z );
167            }
168            return new Coordinate( x, y );
169        }
170    
171        /**
172         * Extends this point with z and m values, so it is a PointZ
173         *
174         * @param zVal
175         * @param mVal
176         */
177        public void extend( double zVal, double mVal ) {
178            z = zVal;
179            m = mVal;
180            isZ = true;
181        }
182    
183        /**
184         * Extends this point with m values, so it is a PointM
185         *
186         * @param mVal
187         */
188        public void extend( double mVal ) {
189            m = mVal;
190            isM = true;
191        }
192    
193        /*
194         * (non-Javadoc)
195         *
196         * @see org.deegree.io.shpapi.Shape#getByteLength()
197         */
198        public int getByteLength() {
199            if ( isZ ) {
200                return 36;
201            }
202            if ( isM ) {
203                return 28;
204            }
205            return 20;
206        }
207    
208        private int readPoint( byte[] bytes, int offset ) {
209            int off = offset;
210            isM = false;
211            isZ = false;
212            x = ByteUtils.readLEDouble( bytes, off );
213    
214            off += 8;
215    
216            y = ByteUtils.readLEDouble( bytes, off );
217    
218            off += 8;
219            return off;
220        }
221    
222        private int readPointZ( byte[] bytes, int offset ) {
223            int off = offset;
224            isM = false;
225            isZ = true;
226            x = ByteUtils.readLEDouble( bytes, off );
227    
228            off += 8;
229    
230            y = ByteUtils.readLEDouble( bytes, off );
231    
232            off += 8;
233    
234            z = ByteUtils.readLEDouble( bytes, off );
235    
236            off += 8;
237    
238            m = ByteUtils.readLEDouble( bytes, off );
239    
240            off += 8;
241    
242            return off;
243        }
244    
245        private int readPointM( byte[] bytes, int offset ) {
246            int off = offset;
247            isM = true;
248            isZ = false;
249            x = ByteUtils.readLEDouble( bytes, off );
250    
251            off += 8;
252    
253            y = ByteUtils.readLEDouble( bytes, off );
254    
255            off += 8;
256    
257            m = ByteUtils.readLEDouble( bytes, off );
258    
259            off += 8;
260            return off;
261        }
262    
263        /*
264         * (non-Javadoc)
265         *
266         * @see org.deegree.io.shpapi.Shape#read(byte[], int)
267         */
268        public int read( byte[] bytes, int offset ) {
269            int off = offset;
270    
271            int type = ByteUtils.readLEInt( bytes, off );
272            off += 4;
273    
274            if ( type == ShapeFile.NULL ) {
275                isNull = true;
276                return off;
277            }
278    
279            if ( type == ShapeFile.POINT ) {
280                return readPoint( bytes, off );
281            }
282    
283            if ( type == ShapeFile.POINTZ ) {
284                return readPointZ( bytes, off );
285            }
286    
287            if ( type == ShapeFile.POINTM ) {
288                return readPointM( bytes, off );
289            }
290    
291            return -1;
292        }
293    
294        private int writePoint( byte[] bytes, int offset ) {
295            int off = offset;
296    
297            ByteUtils.writeLEDouble( bytes, off, x );
298            off += 8;
299    
300            ByteUtils.writeLEDouble( bytes, off, y );
301            off += 8;
302    
303            return off;
304        }
305    
306        private int writePointZ( byte[] bytes, int offset ) {
307            int off = writePoint( bytes, offset );
308    
309            ByteUtils.writeLEDouble( bytes, off, z );
310            off += 8;
311    
312            ByteUtils.writeLEDouble( bytes, off, m );
313            off += 8;
314    
315            return off;
316        }
317    
318        private int writePointM( byte[] bytes, int offset ) {
319            int off = writePoint( bytes, offset );
320    
321            ByteUtils.writeLEDouble( bytes, off, m );
322            off += 8;
323    
324            return off;
325        }
326    
327        /*
328         * (non-Javadoc)
329         *
330         * @see org.deegree.io.shpapi.Shape#write(byte[], int)
331         */
332        public int write( byte[] bytes, int offset ) {
333            if ( isZ ) {
334                ByteUtils.writeLEInt( bytes, offset, ShapeFile.POINTZ );
335                return writePointZ( bytes, offset + 4 );
336            }
337            if ( isM ) {
338                ByteUtils.writeLEInt( bytes, offset, ShapeFile.POINTM );
339                return writePointM( bytes, offset + 4 );
340            }
341    
342            ByteUtils.writeLEInt( bytes, offset, ShapeFile.POINT );
343            return writePoint( bytes, offset + 4 );
344        }
345    
346        /*
347         * (non-Javadoc)
348         *
349         * @see org.deegree.io.shpapi.shape_new.Shape#getType()
350         */
351        public int getType() {
352            if ( isZ ) {
353                return ShapeFile.POINTZ;
354            }
355            if ( isM ) {
356                return ShapeFile.POINTM;
357            }
358            return ShapeFile.POINT;
359        }
360    
361        /**
362         * @return null, points do not have an envelope
363         * @see org.deegree.io.shpapi.shape_new.Shape#getEnvelope()
364         */
365        public ShapeEnvelope getEnvelope() {
366            return null;
367        }
368    
369        /**
370         * This creates a Point object.
371         *
372         * @see org.deegree.io.shpapi.shape_new.Shape#getGeometry()
373         */
374        public Geometry getGeometry()
375                                throws ShapeGeometryException {
376            if ( isNull ) {
377                return null;
378            }
379            if ( isZ ) {
380                return GeometryFactory.createPoint( x, y, z, crs );
381            }
382            return GeometryFactory.createPoint( x, y, crs );
383        }
384    
385        @Override
386        public String toString() {
387            try {
388                return WKTAdapter.export( getGeometry() ).toString();
389            } catch ( GeometryException e ) {
390                return "(unknown)";
391            }
392        }
393    
394    }