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