⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 encodekml.java

📁 电子地图服务器,搭建自己的地图服务
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org.  All rights reserved.
 * This code is licensed under the GPL 2.0 license, availible at the root
 * application directory.
 */
package org.vfny.geoserver.wms.responses.map.kml;

import com.vividsolutions.jts.geom.Envelope;
import org.geotools.data.DataUtilities;
import org.geotools.data.DefaultQuery;
import org.geotools.data.FeatureSource;
import org.geotools.data.Query;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.factory.GeoTools;
import org.geotools.feature.AttributeType;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureType;
import org.geotools.feature.GeometryAttributeType;
import org.geotools.filter.IllegalFilterException;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.image.ImageWorker;
import org.geotools.map.MapContext;
import org.geotools.map.MapLayer;
import org.geotools.referencing.CRS;
import org.geotools.renderer.lite.RendererUtilities;
import org.geotools.renderer.lite.StreamingRenderer;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.vfny.geoserver.wms.WMSMapContext;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.media.jai.GraphicsJAI;


/**
 * @deprecated use {@link KMLTransformer}.
 */
public class EncodeKML {
    /** Standard Logger */
    private static final Logger LOGGER = org.geotools.util.logging.Logging.getLogger(
            "org.vfny.geoserver.responses.wms.map.kml");

    /** Filter factory for creating bounding box filters */
    //private FilterFactory filterFactory = FilterFactoryFinder.createFilterFactory();

    /** the XML and KML header */
    private static final String KML_HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\t"
        + "<kml xmlns=\"http://earth.google.com/kml/2.0\">\n";

    /** the KML closing element */
    private static final String KML_FOOTER = "</kml>\n";

    /**
     * Map context document - layers, styles aoi etc.
     *
     * @uml.property name="mapContext"
     * @uml.associationEnd multiplicity="(1 1)"
     */
    private WMSMapContext mapContext;

    /**
     * Actualy writes the KML out
     *
     * @uml.property name="writer"
     * @uml.associationEnd multiplicity="(0 1)"
     */
    private KMLWriter writer;

    /** Filter factory for creating bounding box filters */
    private FilterFactory filterFactory = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints());

    /** Flag to be monotored by writer loops */
    private boolean abortProcess;

    /**
     * Creates a new EncodeKML object.
     *
     * @param mapContext A full description of the map to be encoded.
     */
    public EncodeKML(WMSMapContext mapContext) {
        this.mapContext = mapContext;
    }

    /**
     * Sets the abort flag.  Active encoding may be halted, but this is not garanteed.
     */
    public void abort() {
        abortProcess = true;
    }

    /**
     * Perform the actual encoding.  May return early if abort it called.
     *
     * @param out Ouput stream to send the data to.
     *
     * @throws IOException Thrown if anything goes wrong whilst writing
     */
    public void encodeKML(final OutputStream out) throws IOException {
        this.writer = new KMLWriter(out, mapContext);
        //once KML supports bbox queries against WMS this can be used to 
        //decimate the geometries based on zoom level.
        //writer.setMinCoordDistance(env.getWidth() / 1000);
        abortProcess = false;

        long t = System.currentTimeMillis();

        try {
            writeHeader();

            ArrayList layerRenderList = new ArrayList(); // not used in straight KML generation
            writeLayers(false, layerRenderList);
            writeFooter();

            this.writer.flush();
            t = System.currentTimeMillis() - t;
            LOGGER.fine(new StringBuffer("KML generated, it took").append(t).append(" ms").toString());
        } catch (IOException ioe) {
            if (abortProcess) {
                LOGGER.fine("KML encoding aborted");

                return;
            } else {
                throw ioe;
            }
        } catch (AbortedException ex) {
            return;
        }
    }

    /**
     * This method is used to encode kml + images and put all the stuff into a KMZ
     * file.
     *
     * @param out the response is a Zipped output stream
     * @throws IOException
     */
    public void encodeKMZ(final ZipOutputStream out) throws IOException {
        this.writer = new KMLWriter(out, mapContext);

        abortProcess = false;

        long t = System.currentTimeMillis();

        try {
            // first we produce the KML file containing the code and the PlaceMarks
            final ZipEntry e = new ZipEntry("wms.kml");
            out.putNextEntry(e);
            writeHeader();

            ArrayList layerRenderList = new ArrayList();
            writeLayers(true, layerRenderList);
            writeFooter();
            this.writer.flush();
            out.closeEntry();

            // then we produce and store all the layer images
            writeImages(out, layerRenderList);

            t = System.currentTimeMillis() - t;
            LOGGER.fine(new StringBuffer("KMZ generated, it took").append(t).append(" ms").toString());
        } catch (IOException ioe) {
            if (abortProcess) {
                LOGGER.fine("KMZ encoding aborted");

                return;
            } else {
                throw ioe;
            }
        } catch (AbortedException ex) {
            return;
        }
    }

    /**
     * Determines whether to return a vector (KML) result of the data or to
     * return an image instead.
     * If the kmscore is 100, then the output should always be vector. If
     * the kmscore is 0, it should always be raster. In between, the number of
     * features is weighed against the kmscore value.
     * kmscore determines whether to return the features as vectors, or as one
     * raster image. It is the point, determined by the user, where X number of
     * features is "too many" and the result should be returned as an image instead.
     *
     * kmscore is logarithmic. The higher the value, the more features it takes
     * to make the algorithm return an image. The lower the kmscore, the fewer
     * features it takes to force an image to be returned.
     * (in use, the formula is exponential: as you increase the KMScore value,
     * the number of features required increases exponentially).
     *
     * @param kmscore the score, between 0 and 100, use to determine what output to use
     * @param numFeatures how many features are being rendered
     * @return true: use just kml vectors, false: use raster result
     */
    private boolean useVectorOutput(int kmscore, int numFeatures) {
        if (kmscore == 100) {
            return true; // vector KML
        }

        if (kmscore == 0) {
            return false; // raster KMZ
        }

        // For numbers in between, determine exponentionally based on kmscore value:
        // 10^(kmscore/15)
        // This results in exponential growth.
        // The lowest bound is 1 feature and the highest bound is 3.98 million features
        // The most useful kmscore values are between 20 and 70 (21 and 46000 features respectively)
        // A good default kmscore value is around 40 (464 features)
        double magic = Math.pow(10, kmscore / 15);

        if (numFeatures > magic) {
            return false; // return raster
        } else {
            return true; // return vector
        }
    }

    /**
    * writes out standard KML header
    *
    * @throws IOException
    */
    private void writeHeader() throws IOException {
        writer.write(KML_HEADER);
    }

    /**
     * writes out standard KML footer
     *
     * @throws IOException DOCUMENT ME!
     */
    private void writeFooter() throws IOException {
        writer.write(KML_FOOTER);
    }

    /**
     * Processes each of the layers within the current mapContext in turn.
     *
     * writeLayers must be called before writeImages in order for the kmScore
     * algorithm to work.
     *
     * @throws IOException
     * @throws AbortedException
     *
     */
    private void writeLayers(final boolean kmz, ArrayList layerRenderList)
        throws IOException, AbortedException {
        MapLayer[] layers = mapContext.getLayers();
        int nLayers = layers.length;

        final int imageWidth = this.mapContext.getMapWidth();
        final int imageHeight = this.mapContext.getMapHeight();

        //final CoordinateReferenceSystem requestedCrs = mapContext.getCoordinateReferenceSystem();
        //writer.setRequestedCRS(requestedCrs);
        //writer.setScreenSize(new Rectangle(imageWidth, imageHeight));
        if (nLayers > 1) { // if we have more than one layer, use the name "GeoServer" to group them
            writer.startDocument("GeoServer", null);
        }

        for (int i = 0; i < nLayers; i++) { // for every layer specified in the request

            MapLayer layer = layers[i];
            writer.startDocument(layer.getTitle(), null);

            //FeatureReader featureReader = null;
            FeatureSource fSource = layer.getFeatureSource();
            FeatureType schema = fSource.getSchema();

            //GeometryAttributeType geometryAttribute = schema.getDefaultGeometry();
            //CoordinateReferenceSystem sourceCrs = geometryAttribute.getCoordinateSystem();
            Rectangle paintArea = new Rectangle(imageWidth, imageHeight);
            AffineTransform worldToScreen = RendererUtilities.worldToScreenTransform(mapContext
                    .getAreaOfInterest(), paintArea);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -