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

📄 kmlnetworklinktransformer.java

📁 电子地图服务器,搭建自己的地图服务
💻 JAVA
字号:
package org.vfny.geoserver.wms.responses.map.kml;

import java.io.IOException;
import java.util.logging.Logger;

import org.geoserver.wms.util.WMSRequests;
import org.geotools.xml.transform.TransformerBase;
import org.geotools.xml.transform.Translator;
import org.vfny.geoserver.global.MapLayerInfo;
import org.vfny.geoserver.wms.requests.GetMapRequest;
import org.xml.sax.ContentHandler;

import com.vividsolutions.jts.geom.Envelope;

/**
 * Encodes a KML document contianing a network link.
 * <p>
 * This transformer transforms a {@link GetMapRequest} object.
 * </p>
 * 
 * @author Justin Deoliveira, The Open Planning Project, jdeolive@openplans.org
 *
 */
public class KMLNetworkLinkTransformer extends TransformerBase {

    /**
     * logger
     */
    static Logger LOGGER = org.geotools.util.logging.Logging.getLogger("org.geoserver.kml");
    
    /**
     * flag controlling wether the network link should be a super overlay.
     */
    boolean encodeAsRegion = false;
 
    public Translator createTranslator(ContentHandler handler) {
        return new KMLNetworkLinkTranslator( handler );
    }
    
    public void setEncodeAsRegion(boolean encodeAsRegion) {
        this.encodeAsRegion = encodeAsRegion;
    }
    
    class KMLNetworkLinkTranslator extends TranslatorSupport {

        public KMLNetworkLinkTranslator(ContentHandler contentHandler) {
            super(contentHandler, null,null);
        }
        
        public void encode(Object o) throws IllegalArgumentException {
            GetMapRequest request = (GetMapRequest) o;
            
            start( "kml" );
            start( "Folder" );
        
            if ( encodeAsRegion ) {
                encodeAsSuperOverlay( request );
            }
            else {
                encodeAsOverlay( request );
            }
            
            //look at
            encodeLookAt( request );
            
            end( "Folder" );
            end( "kml" );
        }
        
        protected void encodeAsSuperOverlay( GetMapRequest request ) {
            MapLayerInfo[] layers = request.getLayers();
            for ( int i = 0; i < layers.length; i++ ) {
                start("NetworkLink");
                element( "name", layers[i].getName() );
                element( "open", "1" );
                element( "visibility", "1" );
             
                //region
                start( "Region" );
                
                Envelope bbox = request.getBbox();
                start( "LatLonAltBox" );
                element( "north", ""+bbox.getMaxY() );
                element( "south", ""+bbox.getMinY() );
                element( "east", ""+bbox.getMaxX() );
                element( "west", ""+bbox.getMinX() );
                end( "LatLonAltBox");
                
                start( "Lod" );
                element( "minLodPixels", "256" );
                element( "maxLodPixels", "-1" );
                end( "Lod" );
                
                end( "Region" );
                
                //link
                start("Link" );
  
                String href = WMSRequests.getGetMapUrl(request, layers[i].getName(),null, null, null);
                start( "href" );
                cdata( href );
                end( "href" );
                
                element( "viewRefreshMode", "onRegion" );
                end( "Link" );
                
                end( "NetworkLink");
            }
        }
        
        protected void encodeAsOverlay( GetMapRequest request ) {
            MapLayerInfo[] layers = request.getLayers();
            for ( int i = 0; i < layers.length; i++ ) {
                start("NetworkLink");
                element( "name", layers[i].getName() );
                element( "open", "1" );
                element( "visibility", "1" );
                
                start( "Url" );
                
                //set bbox to null so its not included in the request, google 
                // earth will append it for us
                request.setBbox(null);
                
                String href = WMSRequests.getGetMapUrl(request, layers[i].getName(),null, null, null);
                start( "href" );
                cdata( href );
                end( "href" );
                
                element( "viewRefreshMode", "onStop" );
                element( "viewRefreshTime", "1" );
                end( "Url" );
                
                end( "NetworkLink" );
            }
        }
        
        private void encodeLookAt(GetMapRequest request){
            
            Envelope e = new Envelope();
            e.setToNull();
            
            for ( int i = 0; i < request.getLayers().length; i++ ) {
                MapLayerInfo layer = request.getLayers()[i];
                
                Envelope b = null;
                try {
                    b = request.getLayers()[i].getLatLongBoundingBox();
                } catch (IOException e1) {
                    LOGGER.warning( "Unable to calculate bounds for " + layer.getName() );
                    continue;
                } 
                if ( e.isNull() ) {
                    e.init( b );
                }
                else {
                    e.expandToInclude( b );
                }
            }
            
            if ( e.isNull() ) {
                return;
            }
            
            double lon1 = e.getMinX();
            double lat1 = e.getMinY();
            double lon2 = e.getMaxX();
            double lat2 = e.getMaxY();
            
            double R_EARTH = 6.371 * 1000000; // meters
            double VIEWER_WIDTH = 22 * Math.PI / 180; // The field of view of the google maps camera, in radians
            double[] p1 = getRect(lon1, lat1, R_EARTH);
            double[] p2 = getRect(lon2, lat2, R_EARTH);
            double[] midpoint = new double[]{
              (p1[0] + p2[0])/2,
                (p1[1] + p2[1])/2,
                (p1[2] + p2[2])/2
            };
            
            midpoint = getGeographic(midpoint[0], midpoint[1], midpoint[2]);
            
            double distance = distance(p1, p2);
            
            double height = distance/ (2 * Math.tan(VIEWER_WIDTH));
            
            LOGGER.fine("lat1: " + lat1 + "; lon1: " + lon1);
            LOGGER.fine("lat2: " + lat2 + "; lon2: " + lon2);
            LOGGER.fine("latmid: " + midpoint[1] + "; lonmid: " + midpoint[0]);
            
            
            start( "LookAt" );
            element( "longitude", ""+midpoint[0] );
            element( "latitude", "" +midpoint[1] );
            element( "altitude", "0" );
            element( "range", ""+ distance );
            element( "tilt", "0" );
            element( "heading", "0" );
            element( "altitudeMode", "clampToGround" );
            end( "LookAt" );
          }
          
          private double[] getRect(double lat, double lon, double radius){
            double theta = (90 - lat) * Math.PI/180;
            double phi   = (90 - lon) * Math.PI/180;
            
            double x = radius * Math.sin(phi) * Math.cos(theta);
            double y = radius * Math.sin(phi) * Math.sin(theta);
            double z = radius * Math.cos(phi);
            return new double[]{x, y, z};
          }
          
          private double[] getGeographic(double x, double y, double z){
            double theta, phi, radius;
            radius = distance(new double[]{x, y, z}, new double[]{0,0,0});
            theta = Math.atan2(Math.sqrt(x * x + y * y) , z);
            phi = Math.atan2(y , x);
            
            double lat = 90 - (theta * 180 / Math.PI);
            double lon = 90 - (phi * 180 / Math.PI);
            
            return new double[]{(lon > 180 ? lon - 360 : lon), lat, radius};
          }
          
          private double distance(double[] p1, double[] p2){
            double dx = p1[0] - p2[0];
            double dy = p1[1] - p2[1];
            double dz = p1[2] - p2[2];
            return Math.sqrt(dx * dx + dy * dy + dz * dz);
          }
    }
}

⌨️ 快捷键说明

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