org.deegree.ogcwebservices.wpvs.j3d.Object3DFactory.java Source code

Java tutorial

Introduction

Here is the source code for org.deegree.ogcwebservices.wpvs.j3d.Object3DFactory.java

Source

/*----------------    FILE HEADER  ------------------------------------------
    
 This file is part of deegree.
 Copyright (C) 2001-2006 by:
 EXSE, Department of Geography, University of Bonn
 http://www.giub.uni-bonn.de/deegree/
 lat/lon GmbH
 http://www.lat-lon.de
    
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.
    
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.
    
 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    
 Contact:
    
 Andreas Poth
 lat/lon GmbH
 Aennchenstr. 19
 53177 Bonn
 Germany
 E-Mail: poth@lat-lon.de
    
 Prof. Dr. Klaus Greve
 Department of Geography
 University of Bonn
 Meckenheimer Allee 166
 53115 Bonn
 Germany
 E-Mail: greve@giub.uni-bonn.de
    
 ---------------------------------------------------------------------------*/
package org.deegree.ogcwebservices.wpvs.j3d;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.media.j3d.Material;
import javax.vecmath.Color3f;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.deegree.datatypes.QualifiedName;
import org.deegree.framework.log.ILogger;
import org.deegree.framework.log.LoggerFactory;
import org.deegree.framework.util.BootLogger;
import org.deegree.framework.util.ImageUtils;
import org.deegree.framework.util.StringTools;
import org.deegree.framework.xml.XMLException;
import org.deegree.framework.xml.XMLFragment;
import org.deegree.framework.xml.XSLTDocument;
import org.deegree.model.feature.Feature;
import org.deegree.model.feature.FeatureCollection;
import org.deegree.model.feature.FeatureProperty;
import org.deegree.model.feature.GMLFeatureCollectionDocument;
import org.deegree.model.filterencoding.AbstractFilter;
import org.deegree.model.filterencoding.Filter;
import org.deegree.model.filterencoding.FilterConstructionException;
import org.deegree.model.spatialschema.Envelope;
import org.deegree.model.spatialschema.GMLGeometryAdapter;
import org.deegree.model.spatialschema.Surface;
import org.deegree.ogcbase.PropertyPath;
import org.xml.sax.SAXException;

/**
 * 
 * 
 *
 * @version $Revision: 1.3 $
 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
 * @author last edited by: $Author: bezema $
 *
 * @version 1.0. $Revision: 1.3 $, $Date: 2006/11/27 16:57:26 $
 *
 * @since 2.0
 */
public class Object3DFactory {

    private static final ILogger LOG = LoggerFactory.getLogger(Object3DFactory.class);

    private URL xslt = Object3DFactory.class.getResource("toWPVS.xsl");

    /**
     * all texture images will be stored on a Map to avoid double loading
     * and creating a BufferedImage from a image source (textureMap property)
     */
    private static Map<String, BufferedImage> textImgMap;

    private static QualifiedName objectID;

    private static QualifiedName textMapQn;

    private static QualifiedName textCoordsQn;

    private static QualifiedName shininessQn;

    private static QualifiedName transparencyQn;

    private static QualifiedName ambientintensityQn;

    private static QualifiedName specularcolorQn;

    private static QualifiedName diffusecolorQn;

    private static QualifiedName emissivecolorQn;
    static {
        try {
            if (textImgMap == null) {
                textImgMap = new HashMap<String, BufferedImage>(200);
                textMapQn = new QualifiedName("app", "texturemap", new URI("http://www.deegree.org/app"));
                textCoordsQn = new QualifiedName("app", "texturecoordinates",
                        new URI("http://www.deegree.org/app"));
                shininessQn = new QualifiedName("app", "shininess", new URI("http://www.deegree.org/app"));
                transparencyQn = new QualifiedName("app", "transparency", new URI("http://www.deegree.org/app"));
                ambientintensityQn = new QualifiedName("app", "ambientintensity",
                        new URI("http://www.deegree.org/app"));
                specularcolorQn = new QualifiedName("app", "specularcolor", new URI("http://www.deegree.org/app"));
                diffusecolorQn = new QualifiedName("app", "diffusecolor", new URI("http://www.deegree.org/app"));
                emissivecolorQn = new QualifiedName("app", "emissivecolor", new URI("http://www.deegree.org/app"));
                objectID = new QualifiedName("app", "fk_feature", new URI("http://www.deegree.org/app"));
            }
        } catch (URISyntaxException e) {
            BootLogger.logError(e.getMessage(), e);
        }
    }

    /**
     * creates a Surface from the passed feature. It is assumed the feature
     * is simple, contains one surfac/polygon geometry and optional has
     * material and/or texture informations. The GML schema for a valid 
     * feature is defined as:
     * <pre>
     *  <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">
     *      <xsd:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/3.1.1/base/feature.xsd"/>
     *       <xsd:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/3.1.1/base/geometryAggregates.xsd"/>
     *       <xsd:element name="WPVS" type="app:WPVSType" substitutionGroup="gml:_Feature"/>
     *       <xsd:complexType name="WPVSType">
     *           <xsd:complexContent>
     *               <xsd:extension base="gml:AbstractFeatureType">
     *                   <xsd:sequence>
     *                       <xsd:element name="fk_feature" type="xsd:double"/>
     *                       <xsd:element name="geometry" type="gml:GeometryPropertyType"/>
     *                       <xsd:element name="shininess" type="xsd:double" minOccurs="0"/>
     *                       <xsd:element name="transparency" type="xsd:double" minOccurs="0"/>
     *                       <xsd:element name="ambientintensity" type="xsd:double" minOccurs="0"/>
     *                       <xsd:element name="specularcolor" type="xsd:string" minOccurs="0"/>
     *                       <xsd:element name="diffusecolor" type="xsd:string" minOccurs="0"/>
     *                       <xsd:element name="emissivecolor" type="xsd:string" minOccurs="0"/>
     *                       <xsd:element name="texturemap" type="xsd:string" minOccurs="0"/>
     *                       <xsd:element name="texturecoordinates" type="xsd:string" minOccurs="0"/>
     *                       <xsd:element name="texturetype" type="xsd:string" minOccurs="0"/>
     *                       <xsd:element name="repeat" type="xsd:integer" minOccurs="0"/>
     *                   </xsd:sequence>
     *               </xsd:extension>
     *           </xsd:complexContent>
     *       </xsd:complexType>
     *   </xsd:schema>
     * </pre> 
     * @param feature
     * @return a DefaultSurface which is derivtive of a Shape3D.
     */
    public DefaultSurface createSurface(Feature feature) {

        double oId = (Double) feature.getDefaultProperty(objectID).getValue(-1d);

        BufferedImage textImage = null;
        FeatureProperty[] fp = feature.getProperties(textMapQn);
        if (fp != null && fp.length > 0) {
            String tmp = (String) feature.getProperties(textMapQn)[0].getValue();
            if ((textImage = textImgMap.get(tmp)) == null) {
                String lt = tmp.toLowerCase();
                try {
                    if (lt.startsWith("file:") || lt.startsWith("http:")) {
                        textImage = ImageUtils.loadImage(new URL(tmp));
                    } else {
                        textImage = ImageUtils.loadImage(tmp);
                    }
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                textImgMap.put(tmp, textImage);
            }
        }
        float[][] textCoords = new float[1][];
        fp = feature.getProperties(textCoordsQn);
        if (fp != null && fp.length > 0) {
            String tmp = (String) feature.getProperties(textCoordsQn)[0].getValue();
            if (tmp != null) {
                textCoords[0] = StringTools.toArrayFloat(tmp, ", ");
            }
        }
        double shininess = (Double) feature.getDefaultProperty(shininessQn).getValue(1d);
        double transparency = (Double) feature.getDefaultProperty(transparencyQn).getValue(0d);
        double ambientintensity = (Double) feature.getDefaultProperty(ambientintensityQn).getValue(1d);
        Color3f ambientcolor = new Color3f((float) ambientintensity, (float) ambientintensity,
                (float) ambientintensity);

        String tmp = (String) feature.getDefaultProperty(specularcolorQn).getValue("1 1 1");
        float[] tmpFl = StringTools.toArrayFloat(tmp.trim(), " ");
        Color3f specularcolor = new Color3f(tmpFl[0], tmpFl[1], tmpFl[2]);

        tmp = (String) feature.getDefaultProperty(diffusecolorQn).getValue("1 1 1");
        tmpFl = StringTools.toArrayFloat(tmp.trim(), " ");
        Color3f diffusecolor = new Color3f(tmpFl[0], tmpFl[1], tmpFl[2]);

        tmp = (String) feature.getDefaultProperty(emissivecolorQn).getValue("1 1 1");
        tmpFl = StringTools.toArrayFloat(tmp.trim(), " ");
        Color3f emissivecolor = new Color3f(tmpFl[0], tmpFl[1], tmpFl[2]);

        Material material = new Material(ambientcolor, emissivecolor, diffusecolor, specularcolor,
                (float) shininess);

        Surface geom = (Surface) feature.getDefaultGeometryPropertyValue();
        LOG.logDebug("3D-Surface: ", geom);

        DefaultSurface surface = null;
        if (textImage != null) {
            surface = new TexturedSurface(feature.getId(), String.valueOf(oId), geom, material,
                    (float) transparency, textImage, textCoords);
        } else {
            surface = new ColoredSurface(feature.getId(), String.valueOf(oId), geom, material,
                    (float) transparency);
        }

        surface.compile();
        return surface;
    }

    public Composite3DObject createComposite3DObject(Feature feature) {
        // TODO
        throw new UnsupportedOperationException();
    }

    /**
     * creates a Composite3DObject from a FeatureCollection
     * @param fc
     * @return
     * @throws IOException 
     */
    public Composite3DObject createComposite3DObject(FeatureCollection fc) throws IOException {

        List<DefaultSurface> list = new ArrayList<DefaultSurface>(fc.size());
        for (int i = 0; i < fc.size(); i++) {
            DefaultSurface sur = createSurface(fc.getFeature(i));
            list.add(sur);
        }
        return new Composite3DObject(fc.getId(), list);
    }

    /**
     * performs a GetFeature request against the passed URL using the also
     * passed featureType and Filter (least one may be <code>null</code>) 
     * 
     * @param url
     * @param featureType
     * @param filter
     * @return
     * @throws HttpException
     * @throws IOException
     * @throws XMLException
     * @throws SAXException
     */
    public Composite3DObject createComposite3DObject(URL url, QualifiedName featureType, Filter filter)
            throws IOException, XMLException {
        StringBuffer sb = new StringBuffer(2000);
        sb.append("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>");
        sb.append("<wfs:GetFeature version=\"1.1.0\" outputFormat=\"text/xml; ");
        sb.append("subtype=gml/3.1.1\" xmlns:wfs=\"http://www.opengis.net/wfs\" ");
        sb.append("xmlns:").append(featureType.getPrefix()).append("='");
        sb.append(featureType.getNamespace().toASCIIString()).append("' ");
        sb.append("><wfs:Query ");
        sb.append("typeName='").append(featureType.getPrefix()).append(':');
        sb.append(featureType.getLocalName()).append("'>");
        if (filter != null) {
            sb.append(filter.toXML());
        }
        sb.append("</wfs:Query></wfs:GetFeature>");

        LOG.logDebug("GetFeature for access 3D objects", sb.toString());

        PostMethod post = new PostMethod("http://localhost:8081/wfs/services");
        StringRequestEntity sre = new StringRequestEntity(sb.toString());
        post.setRequestEntity(sre);
        HttpClient client = new HttpClient();
        client.executeMethod(post);

        GMLFeatureCollectionDocument doc = new GMLFeatureCollectionDocument();
        try {
            doc.load(post.getResponseBodyAsStream(), url.toExternalForm());
        } catch (SAXException e) {
            LOG.logError(e.getMessage(), e);
            throw new XMLException(e);
        }
        return createComposite3DObject(doc);
    }

    /**
     * performs a GetFeature request against the passed URL using the also
     * passed featureType and a @see Filter constructed from the passed
     * envelope
     * 
     * @param url
     * @param featureType
     * @param geomProperty
     * @param envelope
     * @return
     * @throws XMLException
     * @throws IOException
     */
    public Composite3DObject createComposite3DObject(URL url, QualifiedName featureType, PropertyPath geomProperty,
            Envelope envelope) throws XMLException, IOException {
        StringBuffer sb = new StringBuffer(1000);
        sb.append("<ogc:Filter xmlns:ogc=\"http://www.opengis.net/ogc\"");
        sb.append("><ogc:BBOX>");
        sb.append("<ogc:PropertyName>").append(geomProperty.getAsString());
        sb.append("</ogc:PropertyName>");
        sb.append(GMLGeometryAdapter.exportAsBox(envelope));
        sb.append("</ogc:BBOX></ogc:Filter>");

        XMLFragment xml = new XMLFragment();
        try {
            xml.load(new StringReader(sb.toString()), XMLFragment.DEFAULT_URL);
        } catch (SAXException e) {
            LOG.logError(e.getMessage(), e);
            throw new XMLException(e);
        }

        Filter filter = null;
        try {
            filter = AbstractFilter.buildFromDOM(xml.getRootElement());
        } catch (FilterConstructionException e) {
            LOG.logError(e.getMessage(), e);
            throw new XMLException(e);
        }

        return createComposite3DObject(url, featureType, filter);
    }

    /**
     * 
     * @param gml
     * @return
     * @throws IOException
     */
    public Composite3DObject createComposite3DObject(GMLFeatureCollectionDocument gml) throws IOException {

        FeatureCollection fc = null;
        try {
            XSLTDocument xsltDoc = new XSLTDocument(xslt);
            XMLFragment xml = xsltDoc.transform(gml);
            gml = new GMLFeatureCollectionDocument();
            gml.setRootElement(xml.getRootElement());
            fc = gml.parse();
        } catch (Exception e) {
            LOG.logError(e.getMessage(), e);
            throw new IOException("could not load/parse GML feature collection: " + e.getMessage());
        }

        return createComposite3DObject(fc);
    }

}

/* ********************************************************************
 Changes to this class. What the people have been up to:
 $Log: Object3DFactory.java,v $
 Revision 1.3  2006/11/27 16:57:26  bezema
 cleaning up the code
    
 Revision 1.2  2006/11/27 09:07:52  poth
 JNI integration of proj4 has been removed. The CRS functionality now will be done by native deegree code.
    
 Revision 1.1  2006/11/23 11:46:40  bezema
 The initial version of the new wpvs
    
 Revision 1.1  2006/10/23 09:01:25  ap
 *** empty log message ***
    
    
 ********************************************************************** */