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
原文地址:https://www.cnblogs.com/telwanggs/p/6774741.html