001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_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 }