001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/tags/2.1/src/org/deegree/ogcwebservices/wpvs/j3d/Object3DFactory.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2001-2007 by: 006 EXSE, Department of Geography, University of Bonn 007 http://www.giub.uni-bonn.de/deegree/ 008 lat/lon GmbH 009 http://www.lat-lon.de 010 011 This library is free software; you can redistribute it and/or 012 modify it under the terms of the GNU Lesser General Public 013 License as published by the Free Software Foundation; either 014 version 2.1 of the License, or (at your option) any later version. 015 016 This library is distributed in the hope that it will be useful, 017 but WITHOUT ANY WARRANTY; without even the implied warranty of 018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 019 Lesser General Public License for more details. 020 021 You should have received a copy of the GNU Lesser General Public 022 License along with this library; if not, write to the Free Software 023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 024 025 Contact: 026 027 Andreas Poth 028 lat/lon GmbH 029 Aennchenstr. 19 030 53177 Bonn 031 Germany 032 E-Mail: poth@lat-lon.de 033 034 Prof. Dr. Klaus Greve 035 Department of Geography 036 University of Bonn 037 Meckenheimer Allee 166 038 53115 Bonn 039 Germany 040 E-Mail: greve@giub.uni-bonn.de 041 042 ---------------------------------------------------------------------------*/ 043 package org.deegree.ogcwebservices.wpvs.j3d; 044 045 import java.awt.image.BufferedImage; 046 import java.io.IOException; 047 import java.io.InputStream; 048 import java.math.BigDecimal; 049 import java.net.MalformedURLException; 050 import java.net.URI; 051 import java.net.URISyntaxException; 052 import java.net.URL; 053 import java.util.HashMap; 054 import java.util.Map; 055 import java.util.Properties; 056 057 import javax.media.j3d.Material; 058 import javax.vecmath.Color3f; 059 060 import org.deegree.datatypes.QualifiedName; 061 import org.deegree.framework.log.ILogger; 062 import org.deegree.framework.log.LoggerFactory; 063 import org.deegree.framework.util.BootLogger; 064 import org.deegree.framework.util.ImageUtils; 065 import org.deegree.framework.util.StringTools; 066 import org.deegree.model.feature.Feature; 067 import org.deegree.model.feature.FeatureProperty; 068 import org.deegree.model.spatialschema.Surface; 069 070 /** 071 * 072 * 073 * 074 * @version $Revision: 7956 $ 075 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 076 * @author last edited by: $Author: rbezema $ 077 * 078 * $Revision: 7956 $, $Date: 2007-08-09 11:59:18 +0200 (Do, 09 Aug 2007) $ 079 * 080 */ 081 public class Object3DFactory { 082 083 private static InputStream materialURL = Object3DFactory.class.getResourceAsStream( "material.properties" ); 084 085 private static Properties material = new Properties(); 086 static { 087 try { 088 material.load( materialURL ); 089 } catch ( IOException e ) { 090 BootLogger.logError( e.getMessage(), e ); 091 } 092 } 093 094 private static final ILogger LOG = LoggerFactory.getLogger( Object3DFactory.class ); 095 096 // private URL xslt = Object3DFactory.class.getResource( "toWPVS.xsl" ); 097 098 /** 099 * all texture images will be stored on a Map to avoid double loading and creating a 100 * BufferedImage from a image source (textureMap property) 101 */ 102 private static Map<String, BufferedImage> textImgMap; 103 104 private static QualifiedName objectID; 105 106 private static QualifiedName textMapQn; 107 108 private static QualifiedName textCoordsQn; 109 110 private static QualifiedName shininessQn; 111 112 private static QualifiedName transparencyQn; 113 114 private static QualifiedName ambientintensityQn; 115 116 private static QualifiedName specularcolorQn; 117 118 private static QualifiedName diffusecolorQn; 119 120 private static QualifiedName emissivecolorQn; 121 static { 122 try { 123 if ( textImgMap == null ) { 124 textImgMap = new HashMap<String, BufferedImage>( 200 ); 125 textMapQn = new QualifiedName( "app", "texturemap", 126 new URI( "http://www.deegree.org/app" ) ); 127 textCoordsQn = new QualifiedName( "app", "texturecoordinates", 128 new URI( "http://www.deegree.org/app" ) ); 129 shininessQn = new QualifiedName( "app", "shininess", 130 new URI( "http://www.deegree.org/app" ) ); 131 transparencyQn = new QualifiedName( "app", "transparency", 132 new URI( "http://www.deegree.org/app" ) ); 133 ambientintensityQn = new QualifiedName( "app", "ambientintensity", 134 new URI( "http://www.deegree.org/app" ) ); 135 specularcolorQn = new QualifiedName( "app", "specularcolor", 136 new URI( "http://www.deegree.org/app" ) ); 137 diffusecolorQn = new QualifiedName( "app", "diffusecolor", 138 new URI( "http://www.deegree.org/app" ) ); 139 emissivecolorQn = new QualifiedName( "app", "emissivecolor", 140 new URI( "http://www.deegree.org/app" ) ); 141 objectID = new QualifiedName( "app", "fk_feature", 142 new URI( "http://www.deegree.org/app" ) ); 143 } 144 } catch ( URISyntaxException e ) { 145 BootLogger.logError( e.getMessage(), e ); 146 } 147 } 148 149 /** 150 * creates a Surface from the passed feature. It is assumed the feature is simple, contains one 151 * surfac/polygon geometry and optional has material and/or texture informations. The GML schema 152 * for a valid feature is defined as: 153 * 154 * <pre> 155 * <xsd:schema targetNamespace="http://www.deegree.org/app" xmlns:app="http://www.deegree.org/app" xmlns:ogc="http://www.opengis.net/ogc" xmlns:deegreewfs="http://www.deegree.org/wfs" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" attributeFormDefault="unqualified"> 156 * <xsd:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/3.1.1/base/feature.xsd"/> 157 * <xsd:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/3.1.1/base/geometryAggregates.xsd"/> 158 * <xsd:element name="WPVS" type="app:WPVSType" substitutionGroup="gml:_Feature"/> 159 * <xsd:complexType name="WPVSType"> 160 * <xsd:complexContent> 161 * <xsd:extension base="gml:AbstractFeatureType"> 162 * <xsd:sequence> 163 * <xsd:element name="fk_feature" type="xsd:double"/> 164 * <xsd:element name="geometry" type="gml:GeometryPropertyType"/> 165 * <xsd:element name="shininess" type="xsd:double" minOccurs="0"/> 166 * <xsd:element name="transparency" type="xsd:double" minOccurs="0"/> 167 * <xsd:element name="ambientintensity" type="xsd:double" minOccurs="0"/> 168 * <xsd:element name="specularcolor" type="xsd:string" minOccurs="0"/> 169 * <xsd:element name="diffusecolor" type="xsd:string" minOccurs="0"/> 170 * <xsd:element name="emissivecolor" type="xsd:string" minOccurs="0"/> 171 * <xsd:element name="texturemap" type="xsd:string" minOccurs="0"/> 172 * <xsd:element name="texturecoordinates" type="xsd:string" minOccurs="0"/> 173 * <xsd:element name="texturetype" type="xsd:string" minOccurs="0"/> 174 * <xsd:element name="repeat" type="xsd:integer" minOccurs="0"/> 175 * </xsd:sequence> 176 * </xsd:extension> 177 * </xsd:complexContent> 178 * </xsd:complexType> 179 * </xsd:schema> 180 * </pre> 181 * 182 * @param feature 183 * @return a DefaultSurface which is derivtive of a Shape3D. 184 */ 185 public DefaultSurface createSurface( Feature feature ) { 186 187 double oId = -1d; 188 if ( feature.getDefaultProperty( objectID ).getValue( new Double( -1 ) ) instanceof BigDecimal ) { 189 oId = ( (BigDecimal) feature.getDefaultProperty( objectID ).getValue( new Double( -1 ) ) ).doubleValue(); 190 } else if ( feature.getDefaultProperty( objectID ).getValue( new Double( -1 ) ) instanceof Double ) { 191 oId = ( (Double) feature.getDefaultProperty( objectID ).getValue( new Double( -1d ) ) ).doubleValue(); 192 } 193 194 // read texture informations (if available) from feature 195 BufferedImage textImage = null; 196 FeatureProperty[] fp = feature.getProperties( textMapQn ); 197 if ( fp != null && fp.length > 0 ) { 198 String tmp = (String) feature.getProperties( textMapQn )[0].getValue(); 199 if ( tmp != null && ( textImage = textImgMap.get( tmp ) ) == null ) { 200 String lt = tmp.toLowerCase(); 201 try { 202 if ( lt.startsWith( "file:" ) || lt.startsWith( "http:" ) ) { 203 textImage = ImageUtils.loadImage( new URL( tmp ) ); 204 } else { 205 textImage = ImageUtils.loadImage( tmp ); 206 } 207 } catch ( MalformedURLException e ) { 208 e.printStackTrace(); 209 } catch ( IOException e ) { 210 e.printStackTrace(); 211 } 212 textImgMap.put( tmp, textImage ); 213 } 214 } 215 float[][] textCoords = new float[1][]; 216 fp = feature.getProperties( textCoordsQn ); 217 if ( fp != null && fp.length > 0 ) { 218 String tmp = (String) feature.getProperties( textCoordsQn )[0].getValue(); 219 if ( tmp != null ) { 220 textCoords[0] = StringTools.toArrayFloat( tmp, ", " ); 221 } 222 } 223 224 // read color informations from feature. If not available use default values 225 // from material.properties 226 Double shininess = new Double( material.getProperty( "shininess" ) ); 227 shininess = (Double) feature.getDefaultProperty( shininessQn ).getValue( shininess ); 228 Double transparency = new Double( material.getProperty( "transparency" ) ); 229 transparency = (Double) feature.getDefaultProperty( transparencyQn ).getValue( 230 new Double( 231 0 ) ); 232 Double ambientintensity = new Double( material.getProperty( "ambientintensity" ) ); 233 ambientintensity = (Double) feature.getDefaultProperty( ambientintensityQn ).getValue( 234 new Double( 235 1 ) ); 236 Color3f ambientcolor = new Color3f( ambientintensity.floatValue(), 237 ambientintensity.floatValue(), 238 ambientintensity.floatValue() ); 239 240 String tmp = material.getProperty( "specularcolor" ); 241 tmp = (String) feature.getDefaultProperty( specularcolorQn ).getValue( tmp ); 242 float[] tmpFl = StringTools.toArrayFloat( tmp.trim(), " " ); 243 Color3f specularcolor = new Color3f( tmpFl[0], tmpFl[1], tmpFl[2] ); 244 245 tmp = material.getProperty( "diffusecolor" ); 246 tmp = (String) feature.getDefaultProperty( diffusecolorQn ).getValue( tmp ); 247 tmpFl = StringTools.toArrayFloat( tmp.trim(), " " ); 248 Color3f diffusecolor = new Color3f( tmpFl[0], tmpFl[1], tmpFl[2] ); 249 250 tmp = material.getProperty( "emissivecolor" ); 251 tmp = (String) feature.getDefaultProperty( emissivecolorQn ).getValue( tmp ); 252 tmpFl = StringTools.toArrayFloat( tmp.trim(), " " ); 253 Color3f emissivecolor = new Color3f( tmpFl[0], tmpFl[1], tmpFl[2] ); 254 Material material = new Material( ambientcolor, emissivecolor, diffusecolor, specularcolor, 255 shininess.floatValue() ); 256 // for diffuse-color to work the ambient lighting must be switched on 257 material.setColorTarget( Material.AMBIENT_AND_DIFFUSE ); 258 Surface geom = (Surface) feature.getDefaultGeometryPropertyValue(); 259 LOG.logDebug( "3D-Surface: ", geom ); 260 261 DefaultSurface surface = null; 262 if ( textImage != null ) { 263 surface = new TexturedSurface( feature.getId(), String.valueOf( oId ), geom, material, 264 transparency.floatValue(), textImage, textCoords ); 265 } else { 266 surface = new ColoredSurface( feature.getId(), String.valueOf( oId ), geom, material, 267 transparency.floatValue() ); 268 } 269 270 surface.compile(); 271 return surface; 272 } 273 274 }