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 }