001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/io/shpapi/shape_new/ShapePolygon.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 java.util.Arrays; 045 import java.util.Collections; 046 import java.util.List; 047 048 import org.deegree.model.spatialschema.ByteUtils; 049 import org.deegree.model.spatialschema.Curve; 050 import org.deegree.model.spatialschema.Geometry; 051 import org.deegree.model.spatialschema.GeometryException; 052 import org.deegree.model.spatialschema.GeometryFactory; 053 import org.deegree.model.spatialschema.Position; 054 055 import com.vividsolutions.jts.algorithm.CGAlgorithms; 056 import com.vividsolutions.jts.geom.Coordinate; 057 058 /** 059 * <code>ShapePolygon</code> corresponds to the Polygon, PolygonM and PolygonZ shapes of the 060 * shapefile spec. 061 * 062 * @author <a href="mailto:schmitz@lat-lon.de">Andreas Schmitz</a> 063 * @author last edited by: $Author: apoth $ 064 * 065 * @version $Revision: 9342 $, $Date: 2007-12-27 13:32:57 +0100 (Do, 27 Dez 2007) $ 066 */ 067 public class ShapePolygon extends ShapePolyline { 068 069 private boolean normalized; 070 071 /** 072 * Creates a new Polygon/M/Z. 073 * 074 * @param z 075 * @param m 076 */ 077 public ShapePolygon( boolean z, boolean m ) { 078 super( z, m ); 079 } 080 081 /** 082 * Creates a PolygonZ from deegree Curves. 083 * 084 * @param curves 085 */ 086 public ShapePolygon( List<Curve> curves ) { 087 super( curves ); 088 } 089 090 private Coordinate[] getAsCoordinates( ShapePoint[] ps ) { 091 Coordinate[] cs = new Coordinate[ps.length]; 092 093 for ( int i = 0; i < cs.length; ++i ) { 094 cs[i] = ps[i].export(); 095 } 096 097 return cs; 098 } 099 100 /** 101 * Normalizes the orientation etc. of this polygon as required by the shapefile spec. This means 102 * (to my understanding), that the outer ring runs clockwise while the inner rings run 103 * counter-clockwise. 104 */ 105 public void normalize() { 106 if ( normalized ) { 107 return; 108 } 109 110 normalized = true; 111 112 Coordinate[] cs = getAsCoordinates( points[0] ); 113 114 if ( CGAlgorithms.isCCW( cs ) ) { 115 List<ShapePoint> list = Arrays.asList( points[0] ); 116 Collections.reverse( list ); 117 points[0] = list.toArray( new ShapePoint[points[0].length] ); 118 } 119 120 for ( int i = 1; i < points.length; ++i ) { 121 cs = getAsCoordinates( points[i] ); 122 if ( !CGAlgorithms.isCCW( cs ) ) { 123 List<ShapePoint> list = Arrays.asList( points[i] ); 124 Collections.reverse( list ); 125 points[i] = list.toArray( new ShapePoint[points[i].length] ); 126 } 127 } 128 } 129 130 /* 131 * (non-Javadoc) 132 * 133 * @see org.deegree.io.shpapi.Shape#read(byte[], int) 134 */ 135 @Override 136 public int read( byte[] bytes, int offset ) { 137 int off = offset; 138 139 int type = ByteUtils.readLEInt( bytes, off ); 140 off += 4; 141 142 if ( type == ShapeFile.NULL ) { 143 return off; 144 } 145 146 if ( type == ShapeFile.POLYGON ) { 147 return readPolyline( bytes, off ); 148 } 149 150 if ( type == ShapeFile.POLYGONZ ) { 151 return readPolylineZ( bytes, off ); 152 } 153 154 if ( type == ShapeFile.POLYGONM ) { 155 return readPolylineM( bytes, off ); 156 } 157 158 return -1; 159 } 160 161 /** 162 * Note that the normalize method will be called automatically, if it has not been called 163 * before. 164 * 165 * @see org.deegree.io.shpapi.shape_new.Shape#write(byte[], int) 166 */ 167 @Override 168 public int write( byte[] bytes, int offset ) { 169 if ( !normalized ) { 170 normalize(); 171 } 172 if ( isZ ) { 173 ByteUtils.writeLEInt( bytes, offset, ShapeFile.POLYGONZ ); 174 return writePolylineZ( bytes, offset + 4 ); 175 } 176 if ( isM ) { 177 ByteUtils.writeLEInt( bytes, offset, ShapeFile.POLYGONM ); 178 return writePolylineM( bytes, offset + 4 ); 179 } 180 ByteUtils.writeLEInt( bytes, offset, ShapeFile.POLYGON ); 181 return writePolyline( bytes, offset + 4 ); 182 } 183 184 /* 185 * (non-Javadoc) 186 * 187 * @see org.deegree.io.shpapi.shape_new.Shape#getType() 188 */ 189 @Override 190 public int getType() { 191 if ( isZ ) { 192 return ShapeFile.POLYGONZ; 193 } 194 if ( isM ) { 195 return ShapeFile.POLYGONM; 196 } 197 return ShapeFile.POLYGON; 198 } 199 200 /** 201 * This creates a Surface object. 202 */ 203 @Override 204 public Geometry getGeometry() 205 throws ShapeGeometryException { 206 if ( points == null ) { 207 return null; 208 } 209 try { 210 Position[] outer = new Position[points[0].length]; 211 212 Position[][] inner = new Position[points.length - 1][]; 213 214 for ( int i = 0; i < points[0].length; ++i ) { 215 if ( isZ ) { 216 outer[i] = GeometryFactory.createPosition( points[0][i].x, points[0][i].y, points[0][i].z ); 217 } else { 218 outer[i] = GeometryFactory.createPosition( points[0][i].x, points[0][i].y ); 219 } 220 } 221 222 for ( int k = 1; k < points.length; ++k ) { 223 inner[k - 1] = new Position[points[k].length]; 224 for ( int i = 0; i < points[k].length; ++i ) { 225 if ( isZ ) { 226 inner[k - 1][i] = GeometryFactory.createPosition( points[k][i].x, points[k][i].y, 227 points[k][i].z ); 228 } else { 229 inner[k - 1][i] = GeometryFactory.createPosition( points[k][i].x, points[k][i].y ); 230 } 231 } 232 } 233 234 // not sure if interpolation can be null 235 return GeometryFactory.createSurface( outer, inner, null, null ); 236 } catch ( GeometryException e ) { 237 throw new ShapeGeometryException( "Surface could not be constructed from Polygon.", e ); 238 } 239 } 240 241 }