001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/io/shpapi/SHPPolygon.java $
002    
003    /*----------------    FILE HEADER  ------------------------------------------
004     
005    This file is part of deegree.
006    Copyright (C) 2001-2008 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.CurveSegment;
051    import org.deegree.model.spatialschema.GeometryFactory;
052    import org.deegree.model.spatialschema.Ring;
053    import org.deegree.model.spatialschema.Surface;
054    
055    /**
056     * Class representig a two dimensional ESRI Polygon<BR>
057     * 
058     * @version 16.08.2000
059     * @author Andreas Poth
060     */
061    public class SHPPolygon extends SHPGeometry {
062        
063        public int numRings = 0;
064        public int numPoints = 0;  
065        public SHPPolyLine rings = null;
066    
067        
068        
069        /**
070         * constructor: recieves a stream <BR>
071         */
072        public SHPPolygon(byte[] recBuf) {
073            
074            super(recBuf);
075            
076            envelope = ShapeUtils.readBox(recBuf,4);
077            
078            rings = new SHPPolyLine(recBuf);
079            
080            numPoints = rings.numPoints;
081            numRings = rings.numParts;
082            
083        }
084        
085        /**
086         * constructor: recieves an array of arrays of Points  <BR>
087         */
088        public SHPPolygon(Surface[] surface) {
089            
090            try {
091                int count = 0;
092                
093                for (int i = 0; i < surface.length; i++) {
094                    // increment for exterior ring
095                    count++;
096                    // increment for inner rings
097                    Ring[] rings = surface[i].getSurfaceBoundary().getInteriorRings();
098                    if ( rings != null ) {
099                        count += rings.length;
100                    }
101                }
102                
103                Curve[] curves = new Curve[count];
104                
105                count = 0;
106                for (int i = 0; i < surface.length; i++) {
107                    
108                    CurveSegment cs =
109                    surface[i].getSurfaceBoundary().getExteriorRing().getAsCurveSegment();
110                    curves[count++] = GeometryFactory.createCurve( cs );
111                    
112                    Ring[] rings = surface[i].getSurfaceBoundary().getInteriorRings();
113                    if ( rings != null ) {
114                        for (int j = 0; j < rings.length; j++) {
115                            cs =rings[j].getAsCurveSegment();
116                            curves[count++] = GeometryFactory.createCurve( cs );
117                        }
118                    }
119                }
120                
121                rings = new SHPPolyLine(curves);
122                
123                envelope = rings.envelope;
124                
125                numPoints = rings.numPoints;
126                numRings = rings.numParts;
127                
128            } catch(Exception e) {
129                e.printStackTrace();
130            }
131            
132        }
133        
134        /**
135         * method: writeSHPPolygon(byte[] bytearray, int start)<BR>
136         */
137        public byte[] writeSHPPolygon(byte[] bytearray, int start) {
138            
139            int offset = start;
140            
141            double xmin = rings.points[0][0].x;
142            double xmax = rings.points[0][0].x;
143            double ymin = rings.points[0][0].y;
144            double ymax = rings.points[0][0].y;
145            
146            // write shape type identifier
147            ByteUtils.writeLEInt(bytearray, offset, ShapeConst.SHAPE_TYPE_POLYGON);
148            
149            offset += 4;
150            // save offset of the bounding box
151            int tmp1 = offset;
152            
153            // increment offset with size of the bounding box
154            offset += (4*8);
155            
156            // write numRings
157            ByteUtils.writeLEInt(bytearray, offset, numRings);
158            offset += 4;
159            // write numpoints
160            ByteUtils.writeLEInt(bytearray, offset, numPoints);
161            offset += 4;
162            
163            // save offset of the list of offsets for each polyline
164            int tmp2 = offset;
165            
166            // increment offset with numRings
167            offset +=  (4*numRings);
168            
169            int count = 0;
170            for (int i = 0; i < rings.points.length; i++) {
171                
172                // stores the index of the i'th part
173                ByteUtils.writeLEInt(bytearray, tmp2 , count);
174                tmp2 += 4;
175                
176                // write the points of the i'th part and calculate bounding box
177                for (int j = 0; j < rings.points[i].length; j++) {
178                    // number of the current point
179                    count++;
180                    
181                    // calculate bounding box
182                    if (rings.points[i][j].x > xmax) {
183                        xmax = rings.points[i][j].x;
184                    } else if (rings.points[i][j].x < xmin) {
185                        xmin = rings.points[i][j].x;
186                    }
187                    
188                    if (rings.points[i][j].y > ymax) {
189                        ymax = rings.points[i][j].y;
190                    } else if (rings.points[i][j].y < ymin) {
191                        ymin = rings.points[i][j].y;
192                    }
193                    
194                    // write x-coordinate
195                    ByteUtils.writeLEDouble(bytearray, offset, rings.points[i][j].x);
196                    offset += 8;
197                    
198                    // write y-coordinate
199                    ByteUtils.writeLEDouble(bytearray, offset, rings.points[i][j].y);
200                    offset += 8;
201                    
202                }
203                
204            }
205            
206            // jump back to the offset of the bounding box
207            offset = tmp1;
208            
209            // write bounding box to the byte array
210            ByteUtils.writeLEDouble(bytearray, offset, xmin);
211            offset += 8;
212            ByteUtils.writeLEDouble(bytearray, offset, ymin);
213            offset += 8;
214            ByteUtils.writeLEDouble(bytearray, offset, xmax);
215            offset += 8;
216            ByteUtils.writeLEDouble(bytearray, offset, ymax);
217            
218            return bytearray;
219        }
220        
221        /**
222         * returns the polygon shape size in bytes<BR>
223         */
224        public int size() {
225            return 44 + numRings * 4 + numPoints * 16;
226        }
227        
228        
229        
230        public String toString() {
231            
232            return "WKBPOLYGON" + " numRings: " + numRings;
233            
234        }
235    }