001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/ogcwebservices/wpvs/j3d/DefaultSurface.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.ogcwebservices.wpvs.j3d; 037 038 import java.util.ArrayList; 039 import java.util.List; 040 041 import javax.media.j3d.Shape3D; 042 import javax.vecmath.Point3d; 043 044 import org.deegree.model.spatialschema.Geometry; 045 import org.deegree.model.spatialschema.MultiSurface; 046 import org.deegree.model.spatialschema.Position; 047 import org.deegree.model.spatialschema.Ring; 048 import org.deegree.model.spatialschema.Surface; 049 import org.deegree.model.spatialschema.SurfaceBoundary; 050 051 import com.sun.j3d.utils.geometry.GeometryInfo; 052 import com.sun.j3d.utils.geometry.NormalGenerator; 053 054 /** 055 * 056 * 057 * 058 * @version $Revision: 18195 $ 059 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 060 * @author last edited by: $Author: mschneider $ 061 * 062 * @version 1.0. $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18 Jun 2009) $ 063 * 064 * @since 2.0 065 */ 066 public class DefaultSurface extends Shape3D { 067 068 /** 069 * The geometry to create the Shape3D from. 070 */ 071 protected Geometry geometry; 072 073 private String parentID; 074 075 private String objectID; 076 077 /** 078 * 079 * @param objectID 080 * @param parentID 081 * @param geometry 082 */ 083 public DefaultSurface( String objectID, String parentID, Geometry geometry ) { 084 super(); 085 if ( !( geometry instanceof MultiSurface || geometry instanceof Surface ) ) { 086 throw new UnsupportedOperationException( "Currently only surface and multisurfaces are supported" ); 087 } 088 this.geometry = geometry; 089 this.parentID = parentID; 090 this.objectID = objectID; 091 092 /* 093 * System.out.println( "new Appearance" ); Color3f specular = new Color3f( 0.7f, 0.7f, 0.7f ); Color3f white = 094 * new Color3f( 0.4f, 1, 0.4f ); 095 * 096 * Material targetMaterial = new Material(); targetMaterial.setAmbientColor( white ); 097 * targetMaterial.setDiffuseColor( white ); targetMaterial.setSpecularColor( specular ); 098 * targetMaterial.setShininess( 75.0f ); targetMaterial.setLightingEnable( true ); targetMaterial.setCapability( 099 * Material.ALLOW_COMPONENT_WRITE ); // ColoringAttributes ca = new ColoringAttributes(); ca.setShadeModel( 100 * ColoringAttributes.SHADE_GOURAUD ); // Appearance defaultAppearance = new Appearance(); 101 * defaultAppearance.setMaterial( targetMaterial ); defaultAppearance.setColoringAttributes( ca ); // 102 * PolygonAttributes targetPolyAttr = new PolygonAttributes(); targetPolyAttr.setCapability( 103 * PolygonAttributes.ALLOW_MODE_WRITE ); targetPolyAttr.setCapability( PolygonAttributes.ALLOW_NORMAL_FLIP_WRITE ); 104 * targetPolyAttr.setPolygonMode( PolygonAttributes.POLYGON_FILL ); targetPolyAttr.setCullFace( 105 * PolygonAttributes.CULL_NONE ); // pa.setPolygonMode( PolygonAttributes.POLYGON_LINE ); 106 * defaultAppearance.setPolygonAttributes( targetPolyAttr ); setAppearance( defaultAppearance ); 107 */ 108 } 109 110 /** 111 * @return the ID of the Object this Surface is a part of (e.g. the building id if this is a wall) 112 */ 113 public String getParentID() { 114 return parentID; 115 } 116 117 /** 118 * @return the objectID value. 119 */ 120 public String getObjectID() { 121 return objectID; 122 } 123 124 /** 125 * @return a String composited of the parentID and "_" and the objectID 126 */ 127 public String getDefaultSurfaceID() { 128 return parentID + '_' + objectID; 129 } 130 131 /** 132 * 133 * @return the surface geometry encapsulated 134 */ 135 public Geometry getSurfaceGeometry() { 136 return geometry; 137 } 138 139 /** 140 * this method must be called before adding the surface to a Group 141 */ 142 public void compile() { 143 setAppearanceOverrideEnable( true ); 144 addGeometries( geometry ); 145 setCapability( Shape3D.ALLOW_GEOMETRY_READ ); 146 setCapability( Shape3D.ALLOW_GEOMETRY_WRITE ); 147 } 148 149 /** 150 * Adds the given surface. 151 * 152 * @param surface 153 * to be added( only surface and multisurface are currently supported). 154 */ 155 public void addGeometries( org.deegree.model.spatialschema.Geometry surface ) { 156 /** 157 * First create the coordinates and the contours 158 */ 159 if ( surface != null ) { 160 if ( surface instanceof MultiSurface ) { 161 for ( Surface multiSurface : ( (MultiSurface) surface ).getAllSurfaces() ) { 162 GeometryInfo geomInfo = getGeometryInfo( multiSurface ); 163 addGeometry( geomInfo.getGeometryArray() ); 164 } 165 } else if ( surface instanceof Surface ) { 166 // ((extractSurface( (Surface) surface, coordinates, contourCount ); 167 GeometryInfo geomInfo = getGeometryInfo( (Surface) surface ); 168 addGeometry( geomInfo.getGeometryArray() ); 169 } else { 170 throw new IllegalArgumentException( "Don't know how to create a textured surface from given geometry" ); 171 } 172 } 173 } 174 175 /** 176 * Creates a geometry info of the given surface. 177 * 178 * @param surface 179 * @return the geometry info 180 */ 181 public GeometryInfo getGeometryInfo( Surface surface ) { 182 183 GeometryInfo geometryInfo = new GeometryInfo( GeometryInfo.POLYGON_ARRAY ); 184 List<Point3d> coordinates = new ArrayList<Point3d>(); 185 List<Integer> contourCount = new ArrayList<Integer>( 200 ); 186 187 extractSurface( surface, coordinates, contourCount ); 188 189 /** 190 * Now create the geometry info as a polygon array 191 */ 192 geometryInfo.setCoordinates( coordinates.toArray( new Point3d[0] ) ); 193 int[] sc = new int[contourCount.size()]; 194 int stripCountNumber = 0; 195 for ( int i = 0; i < contourCount.size(); ++i ) { 196 sc[i] = contourCount.get( i ).intValue(); 197 stripCountNumber += sc[i]; 198 } 199 geometryInfo.setStripCounts( sc ); 200 // we don't actually need the contours, just an array which has the right length. 201 geometryInfo.setContourCounts( new int[] { sc.length } ); 202 203 // recalculate the normals 204 geometryInfo.recomputeIndices(); 205 NormalGenerator ng = new NormalGenerator(); 206 ng.generateNormals( geometryInfo ); 207 208 // convert the polygon into indexed triangles for faster access. 209 geometryInfo.convertToIndexedTriangles(); 210 return geometryInfo; 211 } 212 213 /** 214 * Extract the actual coordinates of a surface and puts them with in the given list. 215 * 216 * @param surface 217 * to export 218 * @param coordinates 219 * to fill 220 * @param contourCount 221 * will the number of coordinates in a contour (rings). 222 */ 223 protected void extractSurface( Surface surface, List<Point3d> coordinates, List<Integer> contourCount ) { 224 if ( surface != null ) { 225 SurfaceBoundary sb = surface.getSurfaceBoundary(); 226 if ( sb != null ) { 227 Ring outerRing = sb.getExteriorRing(); 228 if ( outerRing != null ) { 229 Position[] pos = outerRing.getPositions(); 230 if ( pos != null ) { 231 // the surface start and end point are the same, ignoring the last node. 232 for ( int i = 0; i < pos.length - 1; ++i ) { 233 coordinates.add( pos[i].getAsPoint3d() ); 234 } 235 contourCount.add( new Integer( pos.length - 1 ) ); 236 } 237 238 Ring[] innerRings = sb.getInteriorRings(); 239 if ( innerRings != null ) { 240 for ( Ring innerRing : innerRings ) { 241 pos = innerRing.getPositions(); 242 if ( pos != null ) { 243 // the surface start and end point are the same, ignoring the last node. 244 for ( int i = 0; i < pos.length - 1; ++i ) { 245 coordinates.add( pos[i].getAsPoint3d() ); 246 } 247 contourCount.add( new Integer( pos.length - 1 ) ); 248 } 249 } 250 } 251 } 252 } 253 } 254 255 } 256 257 /** 258 * @return a String representation of all the geometries inside this surface 259 */ 260 public String getGeometryAsString() { 261 StringBuffer sb = new StringBuffer( numGeometries() ); 262 for ( int i = 0; i < numGeometries(); ++i ) { 263 javax.media.j3d.Geometry ga = getGeometry( i ); 264 sb.append( ga.toString() ); 265 } 266 return sb.toString(); 267 } 268 }