Package org.geoserver.geosearch

Source Code of org.geoserver.geosearch.KMLFeatureDescription

package org.geoserver.geosearch;

import static org.geoserver.ows.util.ResponseUtils.*;

import org.geoserver.ows.URLMangler.URLType;
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.CRS;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.restlet.data.MediaType;
import org.restlet.data.Method;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.data.Status;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryCollection;
import com.vividsolutions.jts.geom.LineSegment;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.Point;


public class KMLFeatureDescription extends AbstractFeatureDescription {
    private Namespace KML =
        Namespace.getNamespace("http://www.opengis.net/kml/2.2");

    private String GEOSERVER_URL;

    public void handle(Request req, Response resp) {
        GEOSERVER_URL = getBaseURL(req);

        if (req.getMethod().equals(Method.GET)) {
            doGet(req, resp);
        } else {
            resp.setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED);
        }
    }

    public void doGet(Request req, Response resp) {
        SimpleFeature f = findFeature(req);
        String prefix = (String)req.getAttributes().get("namespace");
        String type = (String)req.getAttributes().get("layer");
        Document kml = buildKMLDoc(prefix + ":" + type, f);
        resp.setEntity(new JDOMRepresentation(kml, new MediaType("application/vnd.google-earth.kml+xml")));
    }

    private Document buildKMLDoc(String typeName, SimpleFeature f) {
        Document kml = new Document();
        Element root = new Element("kml", KML);
        Element doc = new Element("Document");
        doc.addContent(buildLookAt(f));
        doc.addContent(buildNetworkLink(typeName));
        root.addContent(doc);
        kml.setRootElement(root);
        return kml;
    }

    private Element buildLookAt(SimpleFeature f) {
        Element lookat = new Element("LookAt");
        Coordinate p = getLatLonCentroid(f);
        lookat.addContent(new Element("longitude").addContent("" + p.x));
        lookat.addContent(new Element("latitude").addContent("" + p.y));
        lookat.addContent(new Element("altitude").addContent("0"));
        lookat.addContent(new Element("range").addContent("700"));
        lookat.addContent(new Element("tilt").addContent("0"));
        lookat.addContent(new Element("heading").addContent("0"));
        lookat.addContent(
                new Element("altitudeMode").addContent("clampToGround")
                );
        return lookat;
    }

    private Element buildNetworkLink(String typeName) {
        Element networklink = new Element("NetworkLink");
        networklink.addContent(new Element("name").addContent(
                "Complete " + typeName + " hierarchy"));
        networklink.addContent(new Element("visibility").addContent("1"));

        Element link = new Element("Link");
        link.addContent(new Element("href").addContent(
               
                buildURL(GEOSERVER_URL, "wms/kml?layers=" + typeName, null, URLType.SERVICE)));

        networklink.addContent(link);
        return networklink;
    }

    private Coordinate getLatLonCentroid(SimpleFeature f) {
        Coordinate c = geometryCentroid((Geometry)f.getDefaultGeometry());

        try {
            CoordinateReferenceSystem nativeCRS =
                f.getType().getCoordinateReferenceSystem();
            CoordinateReferenceSystem latLon = CRS.decode("EPSG:4326");

            if (!CRS.equalsIgnoreMetadata(nativeCRS, latLon)) {
                MathTransform xform =
                    CRS.findMathTransform(nativeCRS, latLon, true);
                //convert data bbox to lat/long
                c = JTS.transform(c, null, xform);
            }
        } catch (Exception e) {
            // TODO: Log error
        }

        return c;
    }

    /**
     * Returns the centroid of the geometry, handling a geometry collection.
     * <p>
     * In the case of a collection a multi point containing the centroid of
     * each geometry in the collection is calculated. The first point in the
     * multi point is returned as the cetnroid.
     * </p>
     */
    Coordinate geometryCentroid(Geometry g) {
        // TODO: should the collection case return the centroid of the
        // multi point?
        if (g instanceof GeometryCollection) {
            GeometryCollection gc = (GeometryCollection) g;

            // check for case of single geometry
            if (gc.getNumGeometries() == 1) {
                g = gc.getGeometryN(0);
            } else {
                double maxAreaSoFar = gc.getGeometryN(0).getArea();
                Coordinate centroidToReturn =
                    gc.getGeometryN(0).getCentroid().getCoordinate();

                for (int t = 0; t < gc.getNumGeometries(); t++) {
                    double area = gc.getGeometryN(t).getArea();
                    if (area > maxAreaSoFar) {
                        maxAreaSoFar = area;
                        centroidToReturn =
                            gc.getGeometryN(t).getCentroid().getCoordinate();
                    }
                }

                return centroidToReturn;
            }
        }

        if (g instanceof Point) {
            // thats easy
            return g.getCoordinate();
        } else if (g instanceof LineString) {
            // make sure the point we return is actually on the line
            double tol = 1E-6;
            double mid = g.getLength() / 2d;

            Coordinate[] coords = g.getCoordinates();

            // walk along the linestring until we get to a point where we
            // have two coordinates that straddle the midpoint
            double len = 0d;
            for (int i = 1; i < coords.length; i++) {
                LineSegment line = new LineSegment(coords[i - 1], coords[i]);
                len += line.getLength();

                if (Math.abs(len - mid) < tol) {
                    // close enough
                    return line.getCoordinate(1);
                }

                if (len > mid) {
                    // we have gone past midpoint
                    return line.pointAlong(1 - ((len - mid) / line
                                .getLength()));
                }
            }

            // should never get there
            return g.getCentroid().getCoordinate();
        } else {
            // return the actual centroid
            return g.getCentroid().getCoordinate();
        }
    }
}
TOP

Related Classes of org.geoserver.geosearch.KMLFeatureDescription

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.