001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/ogcwebservices/wpvs/j3d/Object3DFactory.java $
002 /*---------------- FILE HEADER ------------------------------------------
003
004 This file is part of deegree.
005 Copyright (C) 2001-2008 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: 9345 $
075 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
076 * @author last edited by: $Author: apoth $
077 *
078 * $Revision: 9345 $, $Date: 2007-12-27 17:22:25 +0100 (Do, 27 Dez 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 static int numberOfCreatedSurfaces = 0;
097
098 // private URL xslt = Object3DFactory.class.getResource( "toWPVS.xsl" );
099
100 /**
101 * all texture images will be stored on a Map to avoid double loading and creating a BufferedImage from a image
102 * source (textureMap property)
103 */
104 private static Map<String, BufferedImage> textImgMap;
105
106 private static QualifiedName objectID;
107
108 private static QualifiedName textMapQn;
109
110 private static QualifiedName textCoordsQn;
111
112 private static QualifiedName shininessQn;
113
114 private static QualifiedName transparencyQn;
115
116 private static QualifiedName ambientintensityQn;
117
118 private static QualifiedName specularcolorQn;
119
120 private static QualifiedName diffusecolorQn;
121
122 private static QualifiedName emissivecolorQn;
123 static {
124 try {
125 if ( textImgMap == null ) {
126 textImgMap = new HashMap<String, BufferedImage>( 200 );
127 textMapQn = new QualifiedName( "app", "texturemap", new URI( "http://www.deegree.org/app" ) );
128 textCoordsQn = new QualifiedName( "app", "texturecoordinates", new URI( "http://www.deegree.org/app" ) );
129 shininessQn = new QualifiedName( "app", "shininess", new URI( "http://www.deegree.org/app" ) );
130 transparencyQn = new QualifiedName( "app", "transparency", new URI( "http://www.deegree.org/app" ) );
131 ambientintensityQn = new QualifiedName( "app",
132 "ambientintensity",
133 new URI( "http://www.deegree.org/app" ) );
134 specularcolorQn = new QualifiedName( "app", "specularcolor", new URI( "http://www.deegree.org/app" ) );
135 diffusecolorQn = new QualifiedName( "app", "diffusecolor", new URI( "http://www.deegree.org/app" ) );
136 emissivecolorQn = new QualifiedName( "app", "emissivecolor", new URI( "http://www.deegree.org/app" ) );
137 objectID = new QualifiedName( "app", "fk_feature", new URI( "http://www.deegree.org/app" ) );
138 }
139 } catch ( URISyntaxException e ) {
140 BootLogger.logError( e.getMessage(), e );
141 }
142 }
143
144 /**
145 * creates a Surface from the passed feature. It is assumed the feature is simple, contains one surfac/polygon
146 * geometry and optional has material and/or texture informations. The GML schema for a valid feature is defined as:
147 *
148 * <pre>
149 * <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">
150 * <xsd:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/3.1.1/base/feature.xsd"/>
151 * <xsd:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/3.1.1/base/geometryAggregates.xsd"/>
152 * <xsd:element name="WPVS" type="app:WPVSType" substitutionGroup="gml:_Feature"/>
153 * <xsd:complexType name="WPVSType">
154 * <xsd:complexContent>
155 * <xsd:extension base="gml:AbstractFeatureType">
156 * <xsd:sequence>
157 * <xsd:element name="fk_feature" type="xsd:double"/>
158 * <xsd:element name="geometry" type="gml:GeometryPropertyType"/>
159 * <xsd:element name="shininess" type="xsd:double" minOccurs="0"/>
160 * <xsd:element name="transparency" type="xsd:double" minOccurs="0"/>
161 * <xsd:element name="ambientintensity" type="xsd:double" minOccurs="0"/>
162 * <xsd:element name="specularcolor" type="xsd:string" minOccurs="0"/>
163 * <xsd:element name="diffusecolor" type="xsd:string" minOccurs="0"/>
164 * <xsd:element name="emissivecolor" type="xsd:string" minOccurs="0"/>
165 * <xsd:element name="texturemap" type="xsd:string" minOccurs="0"/>
166 * <xsd:element name="texturecoordinates" type="xsd:string" minOccurs="0"/>
167 * <xsd:element name="texturetype" type="xsd:string" minOccurs="0"/>
168 * <xsd:element name="repeat" type="xsd:integer" minOccurs="0"/>
169 * </xsd:sequence>
170 * </xsd:extension>
171 * </xsd:complexContent>
172 * </xsd:complexType>
173 * </xsd:schema>
174 * </pre>
175 *
176 * @param feature
177 * @return a DefaultSurface which is derivtive of a Shape3D.
178 */
179 public DefaultSurface createSurface( Feature feature ) {
180
181 double oId = -1d;
182 if ( feature.getDefaultProperty( objectID ).getValue( new Double( -1 ) ) instanceof BigDecimal ) {
183 oId = ( (BigDecimal) feature.getDefaultProperty( objectID ).getValue( new Double( -1 ) ) ).doubleValue();
184 } else if ( feature.getDefaultProperty( objectID ).getValue( new Double( -1 ) ) instanceof Double ) {
185 oId = ( (Double) feature.getDefaultProperty( objectID ).getValue( new Double( -1d ) ) ).doubleValue();
186 }
187
188 // read texture informations (if available) from feature
189 BufferedImage textImage = null;
190 FeatureProperty[] fp = feature.getProperties( textMapQn );
191 if ( fp != null && fp.length > 0 ) {
192 String tmp = (String) feature.getProperties( textMapQn )[0].getValue();
193 if ( tmp != null && ( textImage = textImgMap.get( tmp ) ) == null ) {
194 String lt = tmp.toLowerCase();
195 try {
196 if ( lt.startsWith( "file:" ) || lt.startsWith( "http:" ) ) {
197 textImage = ImageUtils.loadImage( new URL( tmp ) );
198 } else {
199 textImage = ImageUtils.loadImage( tmp );
200 }
201 } catch ( MalformedURLException e ) {
202 e.printStackTrace();
203 } catch ( IOException e ) {
204 e.printStackTrace();
205 }
206 textImgMap.put( tmp, textImage );
207 }
208 }
209 float[][] textCoords = new float[1][];
210 fp = feature.getProperties( textCoordsQn );
211 if ( fp != null && fp.length > 0 ) {
212 String tmp = (String) fp[0].getValue();
213 LOG.logDebug( "Texture Coordinates: " + tmp );
214 if ( tmp != null ) {
215 textCoords[0] = StringTools.toArrayFloat( tmp, ", " );
216 }
217 }
218
219 // read color informations from feature. If not available use default values
220 // from material.properties
221 Double shininess = new Double( material.getProperty( "shininess" ) );
222 shininess = (Double) feature.getDefaultProperty( shininessQn ).getValue( shininess );
223 Double transparency = new Double( material.getProperty( "transparency" ) );
224 transparency = (Double) feature.getDefaultProperty( transparencyQn ).getValue( new Double( 0 ) );
225 Double ambientintensity = new Double( material.getProperty( "ambientintensity" ) );
226 ambientintensity = (Double) feature.getDefaultProperty( ambientintensityQn ).getValue( new Double( 1 ) );
227 Color3f ambientcolor = new Color3f( ambientintensity.floatValue(),
228 ambientintensity.floatValue(),
229 ambientintensity.floatValue() );
230
231 String tmp = material.getProperty( "specularcolor" );
232 tmp = (String) feature.getDefaultProperty( specularcolorQn ).getValue( tmp );
233 float[] tmpFl = StringTools.toArrayFloat( tmp.trim(), " " );
234 Color3f specularcolor = new Color3f( tmpFl[0], tmpFl[1], tmpFl[2] );
235
236 tmp = material.getProperty( "diffusecolor" );
237 tmp = (String) feature.getDefaultProperty( diffusecolorQn ).getValue( tmp );
238 tmpFl = StringTools.toArrayFloat( tmp.trim(), " " );
239 Color3f diffusecolor = new Color3f( tmpFl[0], tmpFl[1], tmpFl[2] );
240
241 tmp = material.getProperty( "emissivecolor" );
242 tmp = (String) feature.getDefaultProperty( emissivecolorQn ).getValue( tmp );
243 tmpFl = StringTools.toArrayFloat( tmp.trim(), " " );
244 Color3f emissivecolor = new Color3f( tmpFl[0], tmpFl[1], tmpFl[2] );
245 Material material = new Material( ambientcolor,
246 emissivecolor,
247 diffusecolor,
248 specularcolor,
249 shininess.floatValue() );
250 // for diffuse-color to work the ambient lighting must be switched on
251 material.setColorTarget( Material.AMBIENT_AND_DIFFUSE );
252 /**
253 * Please check for the right property here. The defaultPropertyValue just delivers the first geometry defined
254 * in the wfs configuration.
255 */
256 Surface geom = (Surface) feature.getDefaultGeometryPropertyValue();
257 LOG.logDebug( "3D-Surface: ", geom );
258
259 DefaultSurface surface = null;
260 if ( textImage != null ) {
261 surface = new TexturedSurface( feature.getId(),
262 String.valueOf( oId ),
263 geom,
264 material,
265 transparency.floatValue(),
266 textImage,
267 textCoords );
268 } else {
269 surface = new ColoredSurface( feature.getId(),
270 String.valueOf( oId ),
271 geom,
272 material,
273 transparency.floatValue() );
274 }
275 surface.compile();
276 return surface;
277 }
278
279 }