Package org.geoserver.w3ds.xml3d

Source Code of org.geoserver.w3ds.xml3d.XML3DBuilder

/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*
* @author Juha Hyvärinen / Cyberlightning Ltd
*/

package org.geoserver.w3ds.xml3d;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.geoserver.platform.ServiceException;
import org.geoserver.w3ds.types.W3DSLayer;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.util.logging.Logging;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory2;
import org.opengis.feature.Feature;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.AttributeDescriptor;
import org.opengis.geometry.Envelope;
import org.geoserver.w3ds.x3d.GeometryType;
import org.geoserver.w3ds.xml3d.XML3DNode;
import org.geoserver.w3ds.utilities.Format;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;

public class XML3DBuilder {
private final static Logger LOGGER = Logging.getLogger(XML3DBuilder.class);

private BufferedWriter writer = null;

private OutputStream outputStream = null;

private Envelope boundingBox = null;

private XML3DNode xml3dRootNode = null;

private XML3DNode points = null;

private Format requestFormat = null;

private GeometryType geometryType = null;

private XML3DGeometry outputObject = null;

private Long startTime;

private Integer LOD = null;

public XML3DBuilder(Envelope bbox, OutputStream output, Format format) {
    boundingBox = bbox;
    outputStream = output;
    requestFormat = format;

    writer = new BufferedWriter(new OutputStreamWriter(outputStream));
    xml3dRootNode = new XML3DNode();
}

public boolean setLayerAttribute(String name, String value) {
    if (!value.isEmpty()) {
        xml3dRootNode.addXML3DAttribute(new XML3DAttribute(name, value));
        return true;
    }

    return false;
}

private static String getObjectID(W3DSLayer layer, Feature feature) {
    if (!layer.getHasObjectID()) {
        return "unknown";
    }
    String id = layer.getObjectID();
    Object o = feature.getProperty(id).getValue();
    if (o != null) {
        return feature.getProperty(id).getValue().toString();
    }
    return "unknown";
}

private static String getObjectClass(W3DSLayer layer, Feature feature) {
    if (!layer.getHasObjectClass()) {
        return "";
    }
    StringBuilder strb = new StringBuilder();
    for (String cn : layer.getObjectClass()) {
        Object o = feature.getProperty(cn).getValue();
        if (o != null) {
            strb.append(feature.getProperty(cn).getValue().toString() + " ");
        }
    }
    return strb.toString();
}

private XML3DNode newObject(String id, String className) {
    XML3DNode node = new XML3DNode("group");
    xml3dRootNode.addXML3DNode(node);

    node.addXML3DAttribute(new XML3DAttribute("id", id));
    node.addXML3DAttribute(new XML3DAttribute("class", className));

    return node;
}

public void addGeometry(Geometry geometry, String id, String mesh_ref, String className)
        throws IOException {
   
    if (geometry instanceof Polygon || geometry instanceof MultiPolygon) {
        // Initialize output geometry object.
        if (outputObject == null) {
            geometryType = GeometryType.POLYGON;
            if (LOD != null) {
                outputObject = new XML3DGeometry(boundingBox, geometryType, requestFormat, LOD);
            } else {
                outputObject = new XML3DGeometry(boundingBox, geometryType, requestFormat);
            }
        }
        outputObject.addGeometry(geometry);

    } else if (geometry instanceof LineString || geometry instanceof MultiLineString) {
        if (outputObject == null) {
            geometryType = GeometryType.LINESTRING;
            if (LOD != null) {
                outputObject = new XML3DGeometry(boundingBox, geometryType, requestFormat, LOD);
            } else {
                outputObject = new XML3DGeometry(boundingBox, geometryType, requestFormat);
            }
        }
        outputObject.addGeometry(geometry);

    } else if (geometry instanceof Point) {
        geometryType = GeometryType.POINT;
        if (points == null) {
            points = new XML3DNode("objects");
            xml3dRootNode.addXML3DNode(points);
        }
        if (mesh_ref != null) {
            // Create new XML3DNode and add it to the XML3D points node
            XML3DNode point = new XML3DNode("group");
            points.addXML3DNode(point);

            point.addXML3DAttribute(new XML3DAttribute("id", id));
            Coordinate coordinate = geometry.getCoordinate();

            // Transform coordinates to relative coordinates which are calculated from request
            // bounding box.
            double minX = boundingBox.getLowerCorner().getCoordinate()[0]; // Min X
            double minY = boundingBox.getLowerCorner().getCoordinate()[1]; // Min Y

            point.addXML3DAttribute(new XML3DAttribute("translation", String.valueOf(coordinate.x
                    - minX)
                    + " "
                    + String.valueOf(coordinate.z)
                    + " "
                    + String.valueOf(coordinate.y - minY)));

            XML3DNode node = new XML3DNode("mesh");
            XML3DAttribute mesh_src = new XML3DAttribute("src", mesh_ref);
            node.addXML3DAttribute(mesh_src);

            point.addXML3DNode(node);
        } else {
            // XML3D doesn't support drawing of points and therefore point geometry should be used
            // only for external mesh references
            // TODO: implement this case when support is added to XML3D
        }
    } else {
        throw new IllegalArgumentException("Unable to determine geometry type "
                + geometry.getClass());
    }

}

public void setLOD(int lod) {
    LOD = lod;
}

public void addW3DSLayer(W3DSLayer layer) {
    startTime = System.currentTimeMillis();
    FeatureCollection<?, ?> collection = null;
   
    if (layer.haveLODs()) {
        if (LOD != null) {
            FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
            Filter filter = ff.equals(ff.property("lod"), ff.literal(LOD));

            collection = layer.getFeatures(filter);
        } else {
            // If LOD is available but it's not requested, use maximum LOD level as a default
            FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
            Filter filter = ff.equals(ff.property("lod"), ff.literal(10));

            collection = layer.getFeatures(filter);
        }
    } else {
        collection = layer.getFeatures();
    }
   
    FeatureIterator<?> iterator = collection.features();

    try {
        SimpleFeature feature;
        SimpleFeatureType fType;
        List<AttributeDescriptor> types;
        while (iterator.hasNext()) {
            feature = (SimpleFeature) iterator.next();
            fType = feature.getFeatureType();
            types = fType.getAttributeDescriptors();

            Geometry geometry = null;
            String id = null;
            String classname = null;
            String mesh_ref = null;

            for (int j = 0; j < types.size(); j++) {
                Object value = feature.getAttribute(j);

                if (value != null) {
                    if (types.get(j).getLocalName().equalsIgnoreCase("mesh_ref")) {
                        mesh_ref = (String) value;
                    }

                    if (value instanceof Geometry) {
                        id = layer.getLayerInfo().getRequestName() + ":"
                                + getObjectID(layer, feature);
                        classname = getObjectClass(layer, feature);
                        geometry = (Geometry) value;
                    }
                }
            }
            addGeometry(geometry, id, mesh_ref, classname);
        }
        iterator.close();
        iterator = null;

    } catch (Exception exception) {
        ServiceException serviceException = new ServiceException("Error: " + exception.getMessage());
        serviceException.initCause(exception);
        throw serviceException;
    } finally {
        if (iterator != null) {
            iterator.close();
            iterator = null;
        }
    }

}

private void finalizeGeometry() {
    // Shader should be added by client software,
    // since server can't know what user wants to do with generated object.

    if (outputObject != null) {
        // Create new XML3DNode and add it to the XML3D root node
        XML3DNode activeObject = newObject(geometryType.toString(), "NodeClassName");
        activeObject.addXML3DNode(outputObject.toXML3DNode());
    }
}

private void writeXML3D() {
    finalizeGeometry();
    try {
        writer.write(xml3dRootNode.toString());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private void writeHTML() {
    finalizeGeometry();
    try {
        writer.write(xml3dRootNode.toHtml());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

/*
* Write byte array with size information of planar component, resolution
* and elevation data for each point in that planar.
*/
private void writeOctetStream() {
    try {
        if (outputObject != null) {
            outputStream.write(outputObject.toByteArray());
        }
        outputStream.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void writeOutput() {
    if (requestFormat == Format.XML3D) {
        writeXML3D();
    } else if (requestFormat == Format.HTML_XML3D) {
        writeHTML();
    } else if (requestFormat == Format.OCTET_STREAM) {
        writeOctetStream();
    }

    if (LOGGER.isLoggable(Level.INFO))
        LOGGER.info("XML3D request handling took: " + (System.currentTimeMillis() - startTime)
                + "ms");
}

public void close() throws IOException {
    writer.flush();
    writer.close();
}

}
TOP

Related Classes of org.geoserver.w3ds.xml3d.XML3DBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.