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

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

1、添加天地图地图服务

由于上篇转载的平常心的博客对WMSTiledImageLayer已经讲的非常清楚了,这里不再赘述了,看代码:
  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. // // 输出wms元数据信息
  14. // System.out.println(caps.getCapabilityInformation().toString());
  15. // 获取所有图层(这里只有一个,自己用geoserver发布的则可能有很多)
  16. final List<WMSLayerCapabilities> namedLayerCaps = caps.getNamedLayers();
  17. String layerName = null;
  18. for (WMSLayerCapabilities wmsLayerCapabilities : namedLayerCaps)
  19. {
  20. layerName = wmsLayerCapabilities.getName();
  21. }
  22. AVList params = new AVListImpl();
  23. // 图层的名称
  24. params.setValue(AVKey.LAYER_NAMES, layerName);
  25. // 地图服务的协议,这里是OGC:WMS
  26. params.setValue(AVKey.SERVICE_NAME, "OGC:WMS");
  27. // 获得地图的uri,也就是上面定义的uri
  28. params.setValue(AVKey.GET_MAP_URL, uri);
  29. // 在本地缓存文件的名称
  30. params.setValue(AVKey.DATA_CACHE_NAME, layerName);
  31. params.setValue(AVKey.TILE_URL_BUILDER,
  32. new WMSTiledImageLayer.URLBuilder(params));
  33. WMSTiledImageLayer layer = new WMSTiledImageLayer(caps, params);
  34. return layer;
  35. }

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

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

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

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

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

3、WMS服务器管理面板

examples中有个WMSLayerManager,这个demo实现了wms服务的基本管理,只需根据自己的需要修改源代码即可。这里说下我自己修改源代码的方法,首先将需要修改的java文件在改目录下copy一份,名字自取,这样做的好处是不破坏源代码的完整性,因为其他的demo也可能用到这个java文件,避免了大量的修改,改完只需将src导出jar包即可。如下图所示:

改动的不多,都加了注释,可以对比原WMSLayersPanel.java文件看下不同,修改后的SmartScopeWMSLayersPanel源码如下:
  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. import gov.nasa.worldwind.*;
  9. import gov.nasa.worldwind.avlist.*;
  10. import gov.nasa.worldwind.globes.ElevationModel;
  11. import gov.nasa.worldwind.layers.*;
  12. import gov.nasa.worldwind.ogc.wms.*;
  13. import gov.nasa.worldwind.terrain.CompoundElevationModel;
  14. import gov.nasa.worldwind.util.WWUtil;
  15. import gov.nasa.worldwindx.examples.WMSLayersPanel.LayerInfo;
  16. import javax.swing.*;
  17. import javax.swing.border.*;
  18. import java.awt.*;
  19. import java.awt.event.*;
  20. import java.net.*;
  21. import java.util.*;
  22. import java.util.List;
  23. /**
  24. *
  25. * @项目名称:worldwind-1.5.0
  26. * @类名称:SmartScopeWMSLayersPanel
  27. * @类描述: WMS服务图层管理面板
  28. * @创建人:bluce
  29. * @创建时间:2015年2月4日 下午5:09:31
  30. * @修改备注:
  31. * @版本:
  32. */
  33. public class SmartScopeWMSLayersPanel extends JPanel
  34. {
  35. /**
  36. * @Fields serialVersionUID : TODO
  37. */
  38. private static final long serialVersionUID = 1L;
  39. protected static class LayerInfo
  40. {
  41. protected WMSCapabilities caps;
  42. protected AVListImpl params = new AVListImpl();
  43. protected String getTitle()
  44. {
  45. return params.getStringValue(AVKey.DISPLAY_NAME);
  46. }
  47. protected String getName()
  48. {
  49. return params.getStringValue(AVKey.LAYER_NAMES);
  50. }
  51. protected String getAbstract()
  52. {
  53. return params.getStringValue(AVKey.LAYER_ABSTRACT);
  54. }
  55. }
  56. // 所有图层元数据信息
  57. protected String[] servers;
  58. protected List<WMSLayerCapabilities> namedLayerCaps;
  59. protected WorldWindow wwd;
  60. protected URI serverURI;
  61. protected Dimension size;
  62. protected Thread loadingThread;
  63. protected TreeSet<LayerInfo> layerInfos = new TreeSet<LayerInfo>(
  64. new Comparator<LayerInfo>()
  65. {
  66. public int compare(LayerInfo infoA, LayerInfo infoB)
  67. {
  68. String nameA = infoA.getName();
  69. String nameB = infoB.getName();
  70. return nameA.compareTo(nameB);
  71. }
  72. });
  73. public  SmartScopeWMSLayersPanel(String[] servers)
  74. {
  75. }
  76. /**
  77. *
  78. * 创建一个新的实例 SmartScopeWMSLayersPanel.
  79. *
  80. * @param wwd
  81. * @param server
  82. * @param size
  83. * @throws URISyntaxException
  84. */
  85. public SmartScopeWMSLayersPanel(WorldWindow wwd, String[] server,
  86. Dimension size) throws URISyntaxException
  87. {
  88. super(new BorderLayout());
  89. this.servers = server;
  90. this.wwd = wwd;
  91. this.size = size;
  92. this.setPreferredSize(this.size);
  93. this.makeProgressPanel();
  94. // Thread off a retrieval of the server's capabilities document and
  95. // update of this panel.
  96. this.loadingThread = new Thread(new Runnable()
  97. {
  98. public void run()
  99. {
  100. load();
  101. }
  102. });
  103. this.loadingThread.setPriority(Thread.MIN_PRIORITY);
  104. this.loadingThread.start();
  105. }
  106. /**
  107. *
  108. * @方法名称: load ;
  109. * @方法描述: 加载服务 ;
  110. * @参数 :
  111. * @返回类型: void ;
  112. * @创建人:bluce;
  113. * @创建时间:2015年2月5日 上午9:33:23;
  114. * @throws
  115. */
  116. protected void load()
  117. {
  118. WMSCapabilities caps = null;
  119. try
  120. {
  121. for (int i = 0; i < servers.length; i++)
  122. {
  123. this.serverURI = new URI(servers[i].trim());
  124. caps = WMSCapabilities.retrieve(this.serverURI);
  125. caps.parse();
  126. // 获取该服务下的所有图层元数据描述
  127. namedLayerCaps = caps.getNamedLayers();
  128. if (namedLayerCaps == null) return;
  129. try
  130. {
  131. for (WMSLayerCapabilities lc : namedLayerCaps)
  132. {
  133. Set<WMSLayerStyle> styles = lc.getStyles();
  134. if (styles == null || styles.size() == 0)
  135. {
  136. LayerInfo layerInfo = createLayerInfo(caps, lc,
  137. null);
  138. SmartScopeWMSLayersPanel.this.layerInfos
  139. .add(layerInfo);
  140. }
  141. else
  142. {
  143. for (WMSLayerStyle style : styles)
  144. {
  145. LayerInfo layerInfo = createLayerInfo(caps, lc,
  146. style);
  147. SmartScopeWMSLayersPanel.this.layerInfos
  148. .add(layerInfo);
  149. }
  150. }
  151. }
  152. }
  153. catch (Exception e)
  154. {
  155. e.printStackTrace();
  156. return;
  157. }
  158. // 在面板上显示所有图层的名称
  159. EventQueue.invokeLater(new Runnable()
  160. {
  161. public void run()
  162. {
  163. SmartScopeWMSLayersPanel.this.removeAll();
  164. makeLayerInfosPanel(layerInfos);
  165. }
  166. });
  167. }
  168. }
  169. catch (Exception e)
  170. {
  171. e.printStackTrace();
  172. }
  173. // Gather up all the named layers and make a world wind layer for each.
  174. }
  175. public String getServerDisplayString()
  176. {
  177. return this.serverURI.getHost();
  178. }
  179. protected LayerInfo createLayerInfo(WMSCapabilities caps,
  180. WMSLayerCapabilities layerCaps, WMSLayerStyle style)
  181. {
  182. // Create the layer info specified by the layer's capabilities entry and
  183. // the selected style.
  184. LayerInfo linfo = new LayerInfo();
  185. linfo.caps = caps;
  186. linfo.params = new AVListImpl();
  187. linfo.params.setValue(AVKey.LAYER_NAMES, layerCaps.getName());
  188. if (style != null) linfo.params.setValue(AVKey.STYLE_NAMES,
  189. style.getName());
  190. String abs = layerCaps.getLayerAbstract();
  191. if (!WWUtil.isEmpty(abs)) linfo.params.setValue(AVKey.LAYER_ABSTRACT,
  192. abs);
  193. linfo.params.setValue(AVKey.DISPLAY_NAME, makeTitle(caps, linfo));
  194. return linfo;
  195. }
  196. protected void makeLayerInfosPanel(Collection<LayerInfo> layerInfos)
  197. {
  198. // JPanel layersPanel = new JPanel(new GridLayout(0, 1, 0, 4));
  199. // layersPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
  200. JPanel layersPanel = new JPanel();
  201. BoxLayout layout = new BoxLayout(layersPanel, BoxLayout.Y_AXIS);
  202. layersPanel.setLayout(layout);
  203. layersPanel.setFont(new Font("宋体", Font.PLAIN, 10));
  204. // Add the server's layers to the panel.
  205. for (LayerInfo layerInfo : layerInfos)
  206. {
  207. addLayerInfoPanel(layersPanel, SmartScopeWMSLayersPanel.this.wwd,
  208. layerInfo);
  209. }
  210. // Put the name panel in a scroll bar.
  211. JScrollPane scrollPane = new JScrollPane(layersPanel);
  212. scrollPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
  213. scrollPane.setPreferredSize(size);
  214. // Add the scroll bar and name panel to a titled panel that will resize
  215. // with the main window.
  216. // JPanel westPanel = new JPanel(new GridLayout(0, 1, 0, 10));
  217. // westPanel.setBorder(new
  218. // CompoundBorder(BorderFactory.createEmptyBorder(
  219. // 9, 9, 9, 9), new TitledBorder("Layers")));
  220. // westPanel.add(scrollPane);
  221. this.add(scrollPane, BorderLayout.CENTER);
  222. this.revalidate();
  223. }
  224. protected void addLayerInfoPanel(JPanel layersPanel, WorldWindow wwd,
  225. LayerInfo linfo)
  226. {
  227. // Give a layer a button and label and add it to the layer names panel.
  228. LayerInfoAction action = new LayerInfoAction(linfo, wwd);
  229. if (linfo.getAbstract() != null)
  230. {
  231. action.putValue(Action.SHORT_DESCRIPTION, linfo.getAbstract());
  232. JCheckBox jcb = new JCheckBox(action);
  233. jcb.setFont(new Font("宋体", Font.PLAIN, 14));
  234. jcb.setSelected(false);
  235. layersPanel.add(jcb);
  236. }
  237. }
  238. protected class LayerInfoAction extends AbstractAction
  239. {
  240. protected WorldWindow wwd;
  241. protected LayerInfo layerInfo;
  242. protected Object component;
  243. public LayerInfoAction(LayerInfo linfo, WorldWindow wwd)
  244. {
  245. super(linfo.getTitle());
  246. // Capture info we'll need later to control the layer.
  247. this.wwd = wwd;
  248. this.layerInfo = linfo;
  249. }
  250. public void actionPerformed(ActionEvent actionEvent)
  251. {
  252. // If the layer is selected, add it to the world window's current
  253. // model, else remove it from the model.
  254. if (((JCheckBox) actionEvent.getSource()).isSelected())
  255. {
  256. if (this.component == null) this.component = createComponent(
  257. layerInfo.caps, layerInfo.params);
  258. updateComponent(this.component, true);
  259. }
  260. else
  261. {
  262. if (this.component != null) updateComponent(this.component,
  263. false);
  264. }
  265. // Tell the world window to update.
  266. wwd.redraw();
  267. }
  268. }
  269. protected void updateComponent(Object component, boolean enable)
  270. {
  271. if (component instanceof Layer)
  272. {
  273. Layer layer = (Layer) component;
  274. LayerList layers = this.wwd.getModel().getLayers();
  275. layer.setEnabled(enable);
  276. if (enable)
  277. {
  278. if (!layers.contains(layer))
  279. {
  280. ApplicationTemplate.insertBeforePlacenames(this.wwd, layer);
  281. ApplicationTemplate.insertBeforeLayerName(wwd, layer,
  282. "Landsat");
  283. this.firePropertyChange("LayersPanelUpdated", null, layer);
  284. }
  285. }
  286. else
  287. {
  288. layers.remove(layer);
  289. this.firePropertyChange("LayersPanelUpdated", layer, null);
  290. }
  291. }
  292. else if (component instanceof ElevationModel)
  293. {
  294. ElevationModel model = (ElevationModel) component;
  295. CompoundElevationModel compoundModel = (CompoundElevationModel) this.wwd
  296. .getModel().getGlobe().getElevationModel();
  297. if (enable)
  298. {
  299. if (!compoundModel.getElevationModels().contains(model)) compoundModel
  300. .addElevationModel(model);
  301. }
  302. }
  303. }
  304. protected static Object createComponent(WMSCapabilities caps, AVList params)
  305. {
  306. AVList configParams = params.copy(); // Copy to insulate changes from
  307. // the caller.
  308. // Some wms servers are slow, so increase the timeouts and limits used
  309. // by world wind's retrievers.
  310. configParams.setValue(AVKey.URL_CONNECT_TIMEOUT, 30000);
  311. configParams.setValue(AVKey.URL_READ_TIMEOUT, 30000);
  312. configParams.setValue(AVKey.RETRIEVAL_QUEUE_STALE_REQUEST_LIMIT, 60000);
  313. try
  314. {
  315. String factoryKey = getFactoryKeyForCapabilities(caps);
  316. Factory factory = (Factory) WorldWind
  317. .createConfigurationComponent(factoryKey);
  318. return factory.createFromConfigSource(caps, configParams);
  319. }
  320. catch (Exception e)
  321. {
  322. // Ignore the exception, and just return null.
  323. }
  324. return null;
  325. }
  326. protected static String getFactoryKeyForCapabilities(WMSCapabilities caps)
  327. {
  328. boolean hasApplicationBilFormat = false;
  329. Set<String> formats = caps.getImageFormats();
  330. for (String s : formats)
  331. {
  332. if (s.contains("application/bil"))
  333. {
  334. hasApplicationBilFormat = true;
  335. break;
  336. }
  337. }
  338. return hasApplicationBilFormat ? AVKey.ELEVATION_MODEL_FACTORY
  339. : AVKey.LAYER_FACTORY;
  340. }
  341. protected static String makeTitle(WMSCapabilities caps, LayerInfo layerInfo)
  342. {
  343. String layerNames = layerInfo.params.getStringValue(AVKey.LAYER_NAMES);
  344. String styleNames = layerInfo.params.getStringValue(AVKey.STYLE_NAMES);
  345. String[] lNames = layerNames.split(",");
  346. String[] sNames = styleNames != null ? styleNames.split(",") : null;
  347. StringBuilder sb = new StringBuilder();
  348. for (int i = 0; i < lNames.length; i++)
  349. {
  350. if (sb.length() > 0) sb.append(", ");
  351. String layerName = lNames[i];
  352. WMSLayerCapabilities lc = caps.getLayerByName(layerName);
  353. String layerTitle = lc.getTitle();
  354. sb.append(layerTitle != null ? layerTitle : layerName);
  355. if (sNames == null || sNames.length <= i) continue;
  356. String styleName = sNames[i];
  357. WMSLayerStyle style = lc.getStyleByName(styleName);
  358. if (style == null) continue;
  359. sb.append(" : ");
  360. String styleTitle = style.getTitle();
  361. sb.append(styleTitle != null ? styleTitle : styleName);
  362. }
  363. return sb.toString();
  364. }
  365. protected void makeProgressPanel()
  366. {
  367. // Create the panel holding the progress bar during loading.
  368. JPanel outerPanel = new JPanel(new BorderLayout());
  369. outerPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
  370. outerPanel.setPreferredSize(this.size);
  371. JPanel innerPanel = new JPanel(new BorderLayout());
  372. innerPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
  373. JProgressBar progressBar = new JProgressBar();
  374. progressBar.setIndeterminate(true);
  375. innerPanel.add(progressBar, BorderLayout.CENTER);
  376. JButton cancelButton = new JButton("Cancel");
  377. innerPanel.add(cancelButton, BorderLayout.EAST);
  378. cancelButton.addActionListener(new AbstractAction()
  379. {
  380. public void actionPerformed(ActionEvent actionEvent)
  381. {
  382. if (loadingThread.isAlive()) loadingThread.interrupt();
  383. Container c = SmartScopeWMSLayersPanel.this.getParent();
  384. c.remove(SmartScopeWMSLayersPanel.this);
  385. }
  386. });
  387. outerPanel.add(innerPanel, BorderLayout.NORTH);
  388. this.add(outerPanel, BorderLayout.CENTER);
  389. this.revalidate();
  390. }
  391. }

数据下载地址:http://download.csdn.net/detail/liushuo_whu/8426723

World Wind Java开发之十四——添加WMS地图服务资源(转)的更多相关文章

  1. World Wind Java开发之十五——加载三维模型(转)

    之前的一篇博客是关于加载粗三维模型的,见http://blog.csdn.net/giser_whu/article/details/43452703,这个地方还存在着不能加载纹理的问题,一直没呢解决 ...

  2. Java开发学习(十四)----Spring整合Mybatis及Junit

    一.Spring整合Mybatis思路分析 1.1 环境准备 步骤1:准备数据库表 Mybatis是来操作数据库表,所以先创建一个数据库及表 create database spring_db cha ...

  3. World Wind Java开发之十五——载入三维模型

    之前的一篇博客是关于载入粗三维模型的,见http://blog.csdn.net/giser_whu/article/details/43452703,这个地方还存在着不能载入纹理的问题,一直没呢解决 ...

  4. World Wind Java开发之十二——加载粗制三维模型(ExtrudedPolygon)(转)

    ww可以根据DLG图批量生成假三维模型,这对于小区等特征相似的建筑物模型的构建是非常有用的.下面来看如何一步步实现假三维模型的加载: 1.Shp文件的制作 首先在arcmap下数字化几个建筑物,并新建 ...

  5. World Wind Java开发之十——AnalyticSurface栅格渲染(转)

    http://blog.csdn.net/giser_whu/article/details/43017881 1.AnalyticSurfaceDemo ArcGIS下对栅格的各种分级渲染效果是非常 ...

  6. “全栈2019”Java多线程第二十四章:等待唤醒机制详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  7. “全栈2019”Java多线程第十四章:线程与堆栈详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  8. “全栈2019”Java异常第十四章:将异常输出到文本文件中

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异 ...

  9. “全栈2019”Java第八十四章:接口中嵌套接口详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

随机推荐

  1. Scanner类、Random类、ArrayList类

    先写个框架,复习内容后来添加... 先写个框架,复习内容后来添加... 先写个框架,复习内容后来添加... 先写个框架,复习内容后来添加... 先写个框架,复习内容后来添加... 先写个框架,复习内容 ...

  2. centos6.6上安装beef

    https://rvm.io/https://rvm.io/rvm/securityhttps://www.runoob.com/ruby/ruby-installation-unix.htmlhtt ...

  3. 1、gitlab的理论知识

    2.1 svn与git对比 . svn git 分布式 不是 是 在线阅读 不支持 不仅支持,而且可以在线编辑 存储方式 按文件 按元数据 完整性 一般 优 离线工作 日志都没法看 完全没问题 分支 ...

  4. giihub上的关于js的43道题目

    参考 https://github.com/lydiahallie/javascript-questions

  5. PAT甲级——1093 Count PAT's (逻辑类型的题目)

    本文同步发布在CSDN:https://blog.csdn.net/weixin_44385565/article/details/93389073 1093 Count PAT's (25 分)   ...

  6. Jmeter3.2源码编译环境搭建(转)

    1.下载jmeter3.2源码 https://github.com/apache/jmeter/tree/v3_2 https://blog.csdn.net/fly_to_higher/artic ...

  7. java监听器原理理解与实现

    监听器模型涉及以下三个对象,模型图如下: (1)事件:用户对组件的一个操作,称之为一个事件(2)事件源:发生事件的组件就是事件源(3)事件监听器(处理器):监听并负责处理事件的方法 执行顺序如下: 1 ...

  8. MySQL存储过程的动态行转列

    MySQL存储过程中使用动态行转列 最近做项目关于数据报表处理,然而数据库存储格式和报表展现形式不同,需要进行一下行转列的操作,在做上一个项目的时候也看了一下,但是后来换了读取方式,也就没深入研究这个 ...

  9. 如何去除Discuz标题栏中的Powered by Discuz!

    今天修改discuz代码遇到一个问题,就是标题栏中的Powered by Discuz!,很不美观.查资料后得到了解决方法!介绍给大家. 那么如何去掉标题里面的Powered by Discuz!呢? ...

  10. HDU 5452——Minimum Cut——————【树链剖分+差分前缀和】ACdream 1429——Diversion——————【树链剖分】

    Minimum Cut Time Limit: 3000/2000 MS (Java/Others)    Memory Limit: 65535/102400 K (Java/Others)Tota ...