• World Wind Java开发之十四——添加WMS地图服务资源(转)


    数据是GIS的核心,没有数据一切无从谈起,Internet上有很多在线WMS地图服务资源,我们可以好好利用这些数据资源,比如天地图、必应地图、NASA、OGC数据服务等等。

    在我们国家常用的还是天地图的地图服务资源,详见:http://blog.3snews.net/space.php?uid=6955280&do=blog&id=67981,这篇博客列举了一些常用的在线地图服务资源,读者可以自行试下。

    1、添加天地图地图服务

    由于上篇转载的平常心的博客对WMSTiledImageLayer已经讲的非常清楚了,这里不再赘述了,看代码:
    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. public static WMSTiledImageLayer addTianDiTuImage() throws Exception  
    2. {  
    3.     // 请求地图的URL  
    4.     String uri = "http://www.scgis.net.cn/imap/iMapServer/defaultRest/services/newtianditudom/WMS";  
    5.     // WMS  
    6.     WMSCapabilities caps;  
    7.     URI serverURI;  
    8.     serverURI = new URI(uri);  
    9.     // 获得WMSCapabilities对象  
    10.     caps = WMSCapabilities.retrieve(serverURI);  
    11.     // 解析WMSCapabilities数据  
    12.     caps.parse();  
    13.   
    14.     // // 输出wms元数据信息  
    15.     // System.out.println(caps.getCapabilityInformation().toString());  
    16.     // 获取所有图层(这里只有一个,自己用geoserver发布的则可能有很多)  
    17.     final List<WMSLayerCapabilities> namedLayerCaps = caps.getNamedLayers();  
    18.     String layerName = null;  
    19.     for (WMSLayerCapabilities wmsLayerCapabilities : namedLayerCaps)  
    20.     {  
    21.         layerName = wmsLayerCapabilities.getName();  
    22.     }  
    23.     AVList params = new AVListImpl();  
    24.     // 图层的名称  
    25.     params.setValue(AVKey.LAYER_NAMES, layerName);  
    26.     // 地图服务的协议,这里是OGC:WMS  
    27.     params.setValue(AVKey.SERVICE_NAME, "OGC:WMS");  
    28.     // 获得地图的uri,也就是上面定义的uri  
    29.     params.setValue(AVKey.GET_MAP_URL, uri);  
    30.     // 在本地缓存文件的名称  
    31.     params.setValue(AVKey.DATA_CACHE_NAME, layerName);  
    32.     params.setValue(AVKey.TILE_URL_BUILDER,  
    33.             new WMSTiledImageLayer.URLBuilder(params));  
    34.   
    35.     WMSTiledImageLayer layer = new WMSTiledImageLayer(caps, params);  
    36.     return layer;  
    37. }  

    这里添加天地图影像作为底图,效果还是不错的,看下效果图:

    另外,天地图还提供了在线注记底图服务,只需改动上面的地图请求地址即可,看下效果图:

    这里加载的效果要比天地图的在线三维球的效果要好,有兴趣的可以去对比下。另外天地图的在线三维体验还是比较差的,只是单纯的浏览,单是这个体验效果还不是很好,毕竟这是政府的东东,不像Google财大气粗,全球几十万台服务器,天地图的商业化发展之路任重道远啊。

    2、添加Geoserver发布的地图服务

    这里暂时只发布了世界国界和中国县界数据(面和线),这些数据稍后会打包发到我的CSDN资源,大家有需要的可以去下载。为了方便服务资源的管理,在右边添加了一个简单的WMS服务器管理面板,后面仿照ArcCatalog做一个WMS服务器管理的模块。
     

    3、WMS服务器管理面板

    examples中有个WMSLayerManager,这个demo实现了wms服务的基本管理,只需根据自己的需要修改源代码即可。这里说下我自己修改源代码的方法,首先将需要修改的java文件在改目录下copy一份,名字自取,这样做的好处是不破坏源代码的完整性,因为其他的demo也可能用到这个java文件,避免了大量的修改,改完只需将src导出jar包即可。如下图所示:
    改动的不多,都加了注释,可以对比原WMSLayersPanel.java文件看下不同,修改后的SmartScopeWMSLayersPanel源码如下:
    [java] view plain copy
     
     print?在CODE上查看代码片派生到我的代码片
    1. /* 
    2. Copyright (C) 2001, 2006 United States Government 
    3. as represented by the Administrator of the 
    4. National Aeronautics and Space Administration. 
    5. All Rights Reserved. 
    6.  */  
    7. package gov.nasa.worldwindx.examples;  
    8.   
    9. import gov.nasa.worldwind.*;  
    10. import gov.nasa.worldwind.avlist.*;  
    11. import gov.nasa.worldwind.globes.ElevationModel;  
    12. import gov.nasa.worldwind.layers.*;  
    13. import gov.nasa.worldwind.ogc.wms.*;  
    14. import gov.nasa.worldwind.terrain.CompoundElevationModel;  
    15. import gov.nasa.worldwind.util.WWUtil;  
    16. import gov.nasa.worldwindx.examples.WMSLayersPanel.LayerInfo;  
    17.   
    18. import javax.swing.*;  
    19. import javax.swing.border.*;  
    20.   
    21. import java.awt.*;  
    22. import java.awt.event.*;  
    23. import java.net.*;  
    24. import java.util.*;  
    25. import java.util.List;  
    26.   
    27. /** 
    28.  *  
    29.  * @项目名称:worldwind-1.5.0 
    30.  * @类名称:SmartScopeWMSLayersPanel 
    31.  * @类描述: WMS服务图层管理面板 
    32.  * @创建人:bluce 
    33.  * @创建时间:2015年2月4日 下午5:09:31 
    34.  * @修改备注: 
    35.  * @版本: 
    36.  */  
    37. public class SmartScopeWMSLayersPanel extends JPanel  
    38. {  
    39.   
    40.     /** 
    41.      * @Fields serialVersionUID : TODO 
    42.      */  
    43.   
    44.     private static final long serialVersionUID = 1L;  
    45.   
    46.     protected static class LayerInfo  
    47.     {  
    48.         protected WMSCapabilities caps;  
    49.         protected AVListImpl params = new AVListImpl();  
    50.   
    51.         protected String getTitle()  
    52.         {  
    53.             return params.getStringValue(AVKey.DISPLAY_NAME);  
    54.         }  
    55.   
    56.         protected String getName()  
    57.         {  
    58.             return params.getStringValue(AVKey.LAYER_NAMES);  
    59.         }  
    60.   
    61.         protected String getAbstract()  
    62.         {  
    63.             return params.getStringValue(AVKey.LAYER_ABSTRACT);  
    64.         }  
    65.     }  
    66.   
    67.     // 所有图层元数据信息  
    68.     protected String[] servers;  
    69.     protected List<WMSLayerCapabilities> namedLayerCaps;  
    70.     protected WorldWindow wwd;  
    71.     protected URI serverURI;  
    72.     protected Dimension size;  
    73.     protected Thread loadingThread;  
    74.     protected TreeSet<LayerInfo> layerInfos = new TreeSet<LayerInfo>(  
    75.             new Comparator<LayerInfo>()  
    76.             {  
    77.                 public int compare(LayerInfo infoA, LayerInfo infoB)  
    78.                 {  
    79.                     String nameA = infoA.getName();  
    80.                     String nameB = infoB.getName();  
    81.                     return nameA.compareTo(nameB);  
    82.                 }  
    83.             });  
    84.   
    85.       
    86.       
    87.     public  SmartScopeWMSLayersPanel(String[] servers)  
    88.     {  
    89.           
    90.           
    91.     }  
    92.   
    93.     /** 
    94.      *  
    95.      * 创建一个新的实例 SmartScopeWMSLayersPanel. 
    96.      *  
    97.      * @param wwd 
    98.      * @param server 
    99.      * @param size 
    100.      * @throws URISyntaxException 
    101.      */  
    102.     public SmartScopeWMSLayersPanel(WorldWindow wwd, String[] server,  
    103.             Dimension size) throws URISyntaxException  
    104.     {  
    105.         super(new BorderLayout());  
    106.   
    107.         this.servers = server;  
    108.         this.wwd = wwd;  
    109.         this.size = size;  
    110.         this.setPreferredSize(this.size);  
    111.   
    112.         this.makeProgressPanel();  
    113.   
    114.         // Thread off a retrieval of the server's capabilities document and  
    115.         // update of this panel.  
    116.         this.loadingThread = new Thread(new Runnable()  
    117.         {  
    118.             public void run()  
    119.             {  
    120.                 load();  
    121.             }  
    122.         });  
    123.         this.loadingThread.setPriority(Thread.MIN_PRIORITY);  
    124.         this.loadingThread.start();  
    125.     }  
    126.   
    127.     /** 
    128.      *  
    129.      * @方法名称: load ; 
    130.      * @方法描述: 加载服务 ; 
    131.      * @参数 : 
    132.      * @返回类型: void ; 
    133.      * @创建人:bluce; 
    134.      * @创建时间:2015年2月5日 上午9:33:23; 
    135.      * @throws 
    136.      */  
    137.     protected void load()  
    138.     {  
    139.         WMSCapabilities caps = null;  
    140.         try  
    141.         {  
    142.             for (int i = 0; i < servers.length; i++)  
    143.             {  
    144.   
    145.                 this.serverURI = new URI(servers[i].trim());  
    146.                 caps = WMSCapabilities.retrieve(this.serverURI);  
    147.                 caps.parse();  
    148.                 // 获取该服务下的所有图层元数据描述  
    149.                 namedLayerCaps = caps.getNamedLayers();  
    150.   
    151.                 if (namedLayerCaps == null) return;  
    152.   
    153.                 try  
    154.                 {  
    155.                     for (WMSLayerCapabilities lc : namedLayerCaps)  
    156.                     {  
    157.                         Set<WMSLayerStyle> styles = lc.getStyles();  
    158.                         if (styles == null || styles.size() == 0)  
    159.                         {  
    160.                             LayerInfo layerInfo = createLayerInfo(caps, lc,  
    161.                                     null);  
    162.                             SmartScopeWMSLayersPanel.this.layerInfos  
    163.                                     .add(layerInfo);  
    164.                         }  
    165.                         else  
    166.                         {  
    167.                             for (WMSLayerStyle style : styles)  
    168.                             {  
    169.                                 LayerInfo layerInfo = createLayerInfo(caps, lc,  
    170.                                         style);  
    171.                                 SmartScopeWMSLayersPanel.this.layerInfos  
    172.                                         .add(layerInfo);  
    173.                             }  
    174.                         }  
    175.                     }  
    176.                 }  
    177.                 catch (Exception e)  
    178.                 {  
    179.                     e.printStackTrace();  
    180.                     return;  
    181.                 }  
    182.   
    183.                 // 在面板上显示所有图层的名称  
    184.                 EventQueue.invokeLater(new Runnable()  
    185.                 {  
    186.                     public void run()  
    187.                     {  
    188.                         SmartScopeWMSLayersPanel.this.removeAll();  
    189.                         makeLayerInfosPanel(layerInfos);  
    190.                     }  
    191.                 });  
    192.   
    193.             }  
    194.   
    195.         }  
    196.         catch (Exception e)  
    197.         {  
    198.             e.printStackTrace();  
    199.         }  
    200.   
    201.         // Gather up all the named layers and make a world wind layer for each.  
    202.   
    203.     }  
    204.   
    205.     public String getServerDisplayString()  
    206.     {  
    207.         return this.serverURI.getHost();  
    208.     }  
    209.   
    210.     protected LayerInfo createLayerInfo(WMSCapabilities caps,  
    211.             WMSLayerCapabilities layerCaps, WMSLayerStyle style)  
    212.     {  
    213.         // Create the layer info specified by the layer's capabilities entry and  
    214.         // the selected style.  
    215.         LayerInfo linfo = new LayerInfo();  
    216.         linfo.caps = caps;  
    217.         linfo.params = new AVListImpl();  
    218.         linfo.params.setValue(AVKey.LAYER_NAMES, layerCaps.getName());  
    219.         if (style != null) linfo.params.setValue(AVKey.STYLE_NAMES,  
    220.                 style.getName());  
    221.         String abs = layerCaps.getLayerAbstract();  
    222.         if (!WWUtil.isEmpty(abs)) linfo.params.setValue(AVKey.LAYER_ABSTRACT,  
    223.                 abs);  
    224.   
    225.         linfo.params.setValue(AVKey.DISPLAY_NAME, makeTitle(caps, linfo));  
    226.   
    227.         return linfo;  
    228.     }  
    229.   
    230.     protected void makeLayerInfosPanel(Collection<LayerInfo> layerInfos)  
    231.     {  
    232.         // JPanel layersPanel = new JPanel(new GridLayout(0, 1, 0, 4));  
    233.         // layersPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));  
    234.         JPanel layersPanel = new JPanel();  
    235.         BoxLayout layout = new BoxLayout(layersPanel, BoxLayout.Y_AXIS);  
    236.         layersPanel.setLayout(layout);  
    237.         layersPanel.setFont(new Font("宋体", Font.PLAIN, 10));  
    238.         // Add the server's layers to the panel.  
    239.         for (LayerInfo layerInfo : layerInfos)  
    240.         {  
    241.             addLayerInfoPanel(layersPanel, SmartScopeWMSLayersPanel.this.wwd,  
    242.                     layerInfo);  
    243.         }  
    244.   
    245.         // Put the name panel in a scroll bar.  
    246.         JScrollPane scrollPane = new JScrollPane(layersPanel);  
    247.         scrollPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));  
    248.         scrollPane.setPreferredSize(size);  
    249.   
    250.         // Add the scroll bar and name panel to a titled panel that will resize  
    251.         // with the main window.  
    252.         // JPanel westPanel = new JPanel(new GridLayout(0, 1, 0, 10));  
    253.         // westPanel.setBorder(new  
    254.         // CompoundBorder(BorderFactory.createEmptyBorder(  
    255.         // 9, 9, 9, 9), new TitledBorder("Layers")));  
    256.         // westPanel.add(scrollPane);  
    257.         this.add(scrollPane, BorderLayout.CENTER);  
    258.   
    259.         this.revalidate();  
    260.     }  
    261.   
    262.     protected void addLayerInfoPanel(JPanel layersPanel, WorldWindow wwd,  
    263.             LayerInfo linfo)  
    264.     {  
    265.         // Give a layer a button and label and add it to the layer names panel.  
    266.   
    267.         LayerInfoAction action = new LayerInfoAction(linfo, wwd);  
    268.         if (linfo.getAbstract() != null)  
    269.         {  
    270.             action.putValue(Action.SHORT_DESCRIPTION, linfo.getAbstract());  
    271.             JCheckBox jcb = new JCheckBox(action);  
    272.             jcb.setFont(new Font("宋体", Font.PLAIN, 14));  
    273.             jcb.setSelected(false);  
    274.             layersPanel.add(jcb);  
    275.         }  
    276.   
    277.     }  
    278.   
    279.     protected class LayerInfoAction extends AbstractAction  
    280.     {  
    281.         protected WorldWindow wwd;  
    282.         protected LayerInfo layerInfo;  
    283.         protected Object component;  
    284.   
    285.         public LayerInfoAction(LayerInfo linfo, WorldWindow wwd)  
    286.         {  
    287.             super(linfo.getTitle());  
    288.   
    289.             // Capture info we'll need later to control the layer.  
    290.             this.wwd = wwd;  
    291.             this.layerInfo = linfo;  
    292.         }  
    293.   
    294.         public void actionPerformed(ActionEvent actionEvent)  
    295.         {  
    296.             // If the layer is selected, add it to the world window's current  
    297.             // model, else remove it from the model.  
    298.             if (((JCheckBox) actionEvent.getSource()).isSelected())  
    299.             {  
    300.                 if (this.component == null) this.component = createComponent(  
    301.                         layerInfo.caps, layerInfo.params);  
    302.   
    303.                 updateComponent(this.component, true);  
    304.             }  
    305.             else  
    306.             {  
    307.                 if (this.component != null) updateComponent(this.component,  
    308.                         false);  
    309.             }  
    310.   
    311.             // Tell the world window to update.  
    312.             wwd.redraw();  
    313.         }  
    314.     }  
    315.   
    316.     protected void updateComponent(Object component, boolean enable)  
    317.     {  
    318.         if (component instanceof Layer)  
    319.         {  
    320.             Layer layer = (Layer) component;  
    321.             LayerList layers = this.wwd.getModel().getLayers();  
    322.   
    323.             layer.setEnabled(enable);  
    324.   
    325.             if (enable)  
    326.             {  
    327.                 if (!layers.contains(layer))  
    328.                 {  
    329.                     ApplicationTemplate.insertBeforePlacenames(this.wwd, layer);  
    330.                     ApplicationTemplate.insertBeforeLayerName(wwd, layer,  
    331.                             "Landsat");  
    332.                     this.firePropertyChange("LayersPanelUpdated", null, layer);  
    333.                 }  
    334.             }  
    335.             else  
    336.             {  
    337.                 layers.remove(layer);  
    338.                 this.firePropertyChange("LayersPanelUpdated", layer, null);  
    339.             }  
    340.         }  
    341.         else if (component instanceof ElevationModel)  
    342.         {  
    343.             ElevationModel model = (ElevationModel) component;  
    344.             CompoundElevationModel compoundModel = (CompoundElevationModel) this.wwd  
    345.                     .getModel().getGlobe().getElevationModel();  
    346.   
    347.             if (enable)  
    348.             {  
    349.                 if (!compoundModel.getElevationModels().contains(model)) compoundModel  
    350.                         .addElevationModel(model);  
    351.             }  
    352.         }  
    353.     }  
    354.   
    355.     protected static Object createComponent(WMSCapabilities caps, AVList params)  
    356.     {  
    357.         AVList configParams = params.copy(); // Copy to insulate changes from  
    358.                                                 // the caller.  
    359.   
    360.         // Some wms servers are slow, so increase the timeouts and limits used  
    361.         // by world wind's retrievers.  
    362.         configParams.setValue(AVKey.URL_CONNECT_TIMEOUT, 30000);  
    363.         configParams.setValue(AVKey.URL_READ_TIMEOUT, 30000);  
    364.         configParams.setValue(AVKey.RETRIEVAL_QUEUE_STALE_REQUEST_LIMIT, 60000);  
    365.   
    366.         try  
    367.         {  
    368.             String factoryKey = getFactoryKeyForCapabilities(caps);  
    369.             Factory factory = (Factory) WorldWind  
    370.                     .createConfigurationComponent(factoryKey);  
    371.             return factory.createFromConfigSource(caps, configParams);  
    372.         }  
    373.         catch (Exception e)  
    374.         {  
    375.             // Ignore the exception, and just return null.  
    376.         }  
    377.   
    378.         return null;  
    379.     }  
    380.   
    381.     protected static String getFactoryKeyForCapabilities(WMSCapabilities caps)  
    382.     {  
    383.         boolean hasApplicationBilFormat = false;  
    384.   
    385.         Set<String> formats = caps.getImageFormats();  
    386.         for (String s : formats)  
    387.         {  
    388.             if (s.contains("application/bil"))  
    389.             {  
    390.                 hasApplicationBilFormat = true;  
    391.                 break;  
    392.             }  
    393.         }  
    394.   
    395.         return hasApplicationBilFormat ? AVKey.ELEVATION_MODEL_FACTORY  
    396.                 : AVKey.LAYER_FACTORY;  
    397.     }  
    398.   
    399.     protected static String makeTitle(WMSCapabilities caps, LayerInfo layerInfo)  
    400.     {  
    401.         String layerNames = layerInfo.params.getStringValue(AVKey.LAYER_NAMES);  
    402.         String styleNames = layerInfo.params.getStringValue(AVKey.STYLE_NAMES);  
    403.         String[] lNames = layerNames.split(",");  
    404.         String[] sNames = styleNames != null ? styleNames.split(",") : null;  
    405.   
    406.         StringBuilder sb = new StringBuilder();  
    407.         for (int i = 0; i < lNames.length; i++)  
    408.         {  
    409.             if (sb.length() > 0) sb.append(", ");  
    410.   
    411.             String layerName = lNames[i];  
    412.             WMSLayerCapabilities lc = caps.getLayerByName(layerName);  
    413.             String layerTitle = lc.getTitle();  
    414.             sb.append(layerTitle != null ? layerTitle : layerName);  
    415.   
    416.             if (sNames == null || sNames.length <= i) continue;  
    417.   
    418.             String styleName = sNames[i];  
    419.             WMSLayerStyle style = lc.getStyleByName(styleName);  
    420.             if (style == null) continue;  
    421.   
    422.             sb.append(" : ");  
    423.             String styleTitle = style.getTitle();  
    424.             sb.append(styleTitle != null ? styleTitle : styleName);  
    425.         }  
    426.   
    427.         return sb.toString();  
    428.     }  
    429.   
    430.     protected void makeProgressPanel()  
    431.     {  
    432.         // Create the panel holding the progress bar during loading.  
    433.   
    434.         JPanel outerPanel = new JPanel(new BorderLayout());  
    435.         outerPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));  
    436.         outerPanel.setPreferredSize(this.size);  
    437.   
    438.         JPanel innerPanel = new JPanel(new BorderLayout());  
    439.         innerPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));  
    440.         JProgressBar progressBar = new JProgressBar();  
    441.         progressBar.setIndeterminate(true);  
    442.         innerPanel.add(progressBar, BorderLayout.CENTER);  
    443.   
    444.         JButton cancelButton = new JButton("Cancel");  
    445.         innerPanel.add(cancelButton, BorderLayout.EAST);  
    446.         cancelButton.addActionListener(new AbstractAction()  
    447.         {  
    448.             public void actionPerformed(ActionEvent actionEvent)  
    449.             {  
    450.                 if (loadingThread.isAlive()) loadingThread.interrupt();  
    451.   
    452.                 Container c = SmartScopeWMSLayersPanel.this.getParent();  
    453.                 c.remove(SmartScopeWMSLayersPanel.this);  
    454.             }  
    455.         });  
    456.   
    457.         outerPanel.add(innerPanel, BorderLayout.NORTH);  
    458.         this.add(outerPanel, BorderLayout.CENTER);  
    459.         this.revalidate();  
    460.     }  
    461. }  
    数据下载地址:http://download.csdn.net/detail/liushuo_whu/8426723
  • 相关阅读:
    编码 原码 反码 补码
    java垃圾收集器与内存分配策略
    MYSQL 索引 性能优化
    jvm内存溢出性能调优
    JVM内存模型
    线程相关
    Java 设计模式
    synchronized 与 volatile
    ActivityGroup相关--getLocalActivityManager() 以及intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)用法
    [Android] Activity 重复使用
  • 原文地址:https://www.cnblogs.com/telwanggs/p/6774741.html
Copyright © 2020-2023  润新知