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

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

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

1、添加天地图地图服务

由于上篇转载的平常心的博客对WMSTiledImageLayer已经讲的非常清楚了,这里不再赘述了,看代码:
	public static WMSTiledImageLayer addTianDiTuImage() throws Exception
	{
		// 请求地图的URL
		String uri = "http://www.scgis.net.cn/imap/iMapServer/defaultRest/services/newtianditudom/WMS";
		// WMS
		WMSCapabilities caps;
		URI serverURI;
		serverURI = new URI(uri);
		// 获得WMSCapabilities对象
		caps = WMSCapabilities.retrieve(serverURI);
		// 解析WMSCapabilities数据
		caps.parse();

		// // 输出wms元数据信息
		// System.out.println(caps.getCapabilityInformation().toString());
		// 获取所有图层(这里只有一个,自己用geoserver发布的则可能有很多)
		final List<WMSLayerCapabilities> namedLayerCaps = caps.getNamedLayers();
		String layerName = null;
		for (WMSLayerCapabilities wmsLayerCapabilities : namedLayerCaps)
		{
			layerName = wmsLayerCapabilities.getName();
		}
		AVList params = new AVListImpl();
		// 图层的名称
		params.setValue(AVKey.LAYER_NAMES, layerName);
		// 地图服务的协议,这里是OGC:WMS
		params.setValue(AVKey.SERVICE_NAME, "OGC:WMS");
		// 获得地图的uri,也就是上面定义的uri
		params.setValue(AVKey.GET_MAP_URL, uri);
		// 在本地缓存文件的名称
		params.setValue(AVKey.DATA_CACHE_NAME, layerName);
		params.setValue(AVKey.TILE_URL_BUILDER,
				new WMSTiledImageLayer.URLBuilder(params));

		WMSTiledImageLayer layer = new WMSTiledImageLayer(caps, params);
		return layer;
	}

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



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


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

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

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


3、WMS服务器管理面板

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

改动的不多,都加了注释,可以对比原WMSLayersPanel.java文件看下不同,修改后的SmartScopeWMSLayersPanel源码如下:
/*
Copyright (C) 2001, 2006 United States Government
as represented by the Administrator of the
National Aeronautics and Space Administration.
All Rights Reserved.
 */
package gov.nasa.worldwindx.examples;

import gov.nasa.worldwind.*;
import gov.nasa.worldwind.avlist.*;
import gov.nasa.worldwind.globes.ElevationModel;
import gov.nasa.worldwind.layers.*;
import gov.nasa.worldwind.ogc.wms.*;
import gov.nasa.worldwind.terrain.CompoundElevationModel;
import gov.nasa.worldwind.util.WWUtil;
import gov.nasa.worldwindx.examples.WMSLayersPanel.LayerInfo;

import javax.swing.*;
import javax.swing.border.*;

import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.util.*;
import java.util.List;

/**
 * 
 * @项目名称:worldwind-1.5.0
 * @类名称:SmartScopeWMSLayersPanel
 * @类描述: WMS服务图层管理面板
 * @创建人:bluce
 * @创建时间:2015年2月4日 下午5:09:31
 * @修改备注:
 * @版本:
 */
public class SmartScopeWMSLayersPanel extends JPanel
{

	/**
	 * @Fields serialVersionUID : TODO
	 */

	private static final long serialVersionUID = 1L;

	protected static class LayerInfo
	{
		protected WMSCapabilities caps;
		protected AVListImpl params = new AVListImpl();

		protected String getTitle()
		{
			return params.getStringValue(AVKey.DISPLAY_NAME);
		}

		protected String getName()
		{
			return params.getStringValue(AVKey.LAYER_NAMES);
		}

		protected String getAbstract()
		{
			return params.getStringValue(AVKey.LAYER_ABSTRACT);
		}
	}

	// 所有图层元数据信息
	protected String[] servers;
	protected List<WMSLayerCapabilities> namedLayerCaps;
	protected WorldWindow wwd;
	protected URI serverURI;
	protected Dimension size;
	protected Thread loadingThread;
	protected TreeSet<LayerInfo> layerInfos = new TreeSet<LayerInfo>(
			new Comparator<LayerInfo>()
			{
				public int compare(LayerInfo infoA, LayerInfo infoB)
				{
					String nameA = infoA.getName();
					String nameB = infoB.getName();
					return nameA.compareTo(nameB);
				}
			});

	
	
	public  SmartScopeWMSLayersPanel(String[] servers)
	{
		
		
	}

	/**
	 * 
	 * 创建一个新的实例 SmartScopeWMSLayersPanel.
	 * 
	 * @param wwd
	 * @param server
	 * @param size
	 * @throws URISyntaxException
	 */
	public SmartScopeWMSLayersPanel(WorldWindow wwd, String[] server,
			Dimension size) throws URISyntaxException
	{
		super(new BorderLayout());

		this.servers = server;
		this.wwd = wwd;
		this.size = size;
		this.setPreferredSize(this.size);

		this.makeProgressPanel();

		// Thread off a retrieval of the server's capabilities document and
		// update of this panel.
		this.loadingThread = new Thread(new Runnable()
		{
			public void run()
			{
				load();
			}
		});
		this.loadingThread.setPriority(Thread.MIN_PRIORITY);
		this.loadingThread.start();
	}

	/**
	 * 
	 * @方法名称: load ;
	 * @方法描述: 加载服务 ;
	 * @参数 :
	 * @返回类型: void ;
	 * @创建人:bluce;
	 * @创建时间:2015年2月5日 上午9:33:23;
	 * @throws
	 */
	protected void load()
	{
		WMSCapabilities caps = null;
		try
		{
			for (int i = 0; i < servers.length; i++)
			{

				this.serverURI = new URI(servers[i].trim());
				caps = WMSCapabilities.retrieve(this.serverURI);
				caps.parse();
				// 获取该服务下的所有图层元数据描述
				namedLayerCaps = caps.getNamedLayers();

				if (namedLayerCaps == null) return;

				try
				{
					for (WMSLayerCapabilities lc : namedLayerCaps)
					{
						Set<WMSLayerStyle> styles = lc.getStyles();
						if (styles == null || styles.size() == 0)
						{
							LayerInfo layerInfo = createLayerInfo(caps, lc,
									null);
							SmartScopeWMSLayersPanel.this.layerInfos
									.add(layerInfo);
						}
						else
						{
							for (WMSLayerStyle style : styles)
							{
								LayerInfo layerInfo = createLayerInfo(caps, lc,
										style);
								SmartScopeWMSLayersPanel.this.layerInfos
										.add(layerInfo);
							}
						}
					}
				}
				catch (Exception e)
				{
					e.printStackTrace();
					return;
				}

				// 在面板上显示所有图层的名称
				EventQueue.invokeLater(new Runnable()
				{
					public void run()
					{
						SmartScopeWMSLayersPanel.this.removeAll();
						makeLayerInfosPanel(layerInfos);
					}
				});

			}

		}
		catch (Exception e)
		{
			e.printStackTrace();
		}

		// Gather up all the named layers and make a world wind layer for each.

	}

	public String getServerDisplayString()
	{
		return this.serverURI.getHost();
	}

	protected LayerInfo createLayerInfo(WMSCapabilities caps,
			WMSLayerCapabilities layerCaps, WMSLayerStyle style)
	{
		// Create the layer info specified by the layer's capabilities entry and
		// the selected style.
		LayerInfo linfo = new LayerInfo();
		linfo.caps = caps;
		linfo.params = new AVListImpl();
		linfo.params.setValue(AVKey.LAYER_NAMES, layerCaps.getName());
		if (style != null) linfo.params.setValue(AVKey.STYLE_NAMES,
				style.getName());
		String abs = layerCaps.getLayerAbstract();
		if (!WWUtil.isEmpty(abs)) linfo.params.setValue(AVKey.LAYER_ABSTRACT,
				abs);

		linfo.params.setValue(AVKey.DISPLAY_NAME, makeTitle(caps, linfo));

		return linfo;
	}

	protected void makeLayerInfosPanel(Collection<LayerInfo> layerInfos)
	{
		// JPanel layersPanel = new JPanel(new GridLayout(0, 1, 0, 4));
		// layersPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
		JPanel layersPanel = new JPanel();
		BoxLayout layout = new BoxLayout(layersPanel, BoxLayout.Y_AXIS);
		layersPanel.setLayout(layout);
		layersPanel.setFont(new Font("宋体", Font.PLAIN, 10));
		// Add the server's layers to the panel.
		for (LayerInfo layerInfo : layerInfos)
		{
			addLayerInfoPanel(layersPanel, SmartScopeWMSLayersPanel.this.wwd,
					layerInfo);
		}

		// Put the name panel in a scroll bar.
		JScrollPane scrollPane = new JScrollPane(layersPanel);
		scrollPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
		scrollPane.setPreferredSize(size);

		// Add the scroll bar and name panel to a titled panel that will resize
		// with the main window.
		// JPanel westPanel = new JPanel(new GridLayout(0, 1, 0, 10));
		// westPanel.setBorder(new
		// CompoundBorder(BorderFactory.createEmptyBorder(
		// 9, 9, 9, 9), new TitledBorder("Layers")));
		// westPanel.add(scrollPane);
		this.add(scrollPane, BorderLayout.CENTER);

		this.revalidate();
	}

	protected void addLayerInfoPanel(JPanel layersPanel, WorldWindow wwd,
			LayerInfo linfo)
	{
		// Give a layer a button and label and add it to the layer names panel.

		LayerInfoAction action = new LayerInfoAction(linfo, wwd);
		if (linfo.getAbstract() != null)
		{
			action.putValue(Action.SHORT_DESCRIPTION, linfo.getAbstract());
			JCheckBox jcb = new JCheckBox(action);
			jcb.setFont(new Font("宋体", Font.PLAIN, 14));
			jcb.setSelected(false);
			layersPanel.add(jcb);
		}

	}

	protected class LayerInfoAction extends AbstractAction
	{
		protected WorldWindow wwd;
		protected LayerInfo layerInfo;
		protected Object component;

		public LayerInfoAction(LayerInfo linfo, WorldWindow wwd)
		{
			super(linfo.getTitle());

			// Capture info we'll need later to control the layer.
			this.wwd = wwd;
			this.layerInfo = linfo;
		}

		public void actionPerformed(ActionEvent actionEvent)
		{
			// If the layer is selected, add it to the world window's current
			// model, else remove it from the model.
			if (((JCheckBox) actionEvent.getSource()).isSelected())
			{
				if (this.component == null) this.component = createComponent(
						layerInfo.caps, layerInfo.params);

				updateComponent(this.component, true);
			}
			else
			{
				if (this.component != null) updateComponent(this.component,
						false);
			}

			// Tell the world window to update.
			wwd.redraw();
		}
	}

	protected void updateComponent(Object component, boolean enable)
	{
		if (component instanceof Layer)
		{
			Layer layer = (Layer) component;
			LayerList layers = this.wwd.getModel().getLayers();

			layer.setEnabled(enable);

			if (enable)
			{
				if (!layers.contains(layer))
				{
					ApplicationTemplate.insertBeforePlacenames(this.wwd, layer);
					ApplicationTemplate.insertBeforeLayerName(wwd, layer,
							"Landsat");
					this.firePropertyChange("LayersPanelUpdated", null, layer);
				}
			}
			else
			{
				layers.remove(layer);
				this.firePropertyChange("LayersPanelUpdated", layer, null);
			}
		}
		else if (component instanceof ElevationModel)
		{
			ElevationModel model = (ElevationModel) component;
			CompoundElevationModel compoundModel = (CompoundElevationModel) this.wwd
					.getModel().getGlobe().getElevationModel();

			if (enable)
			{
				if (!compoundModel.getElevationModels().contains(model)) compoundModel
						.addElevationModel(model);
			}
		}
	}

	protected static Object createComponent(WMSCapabilities caps, AVList params)
	{
		AVList configParams = params.copy(); // Copy to insulate changes from
												// the caller.

		// Some wms servers are slow, so increase the timeouts and limits used
		// by world wind's retrievers.
		configParams.setValue(AVKey.URL_CONNECT_TIMEOUT, 30000);
		configParams.setValue(AVKey.URL_READ_TIMEOUT, 30000);
		configParams.setValue(AVKey.RETRIEVAL_QUEUE_STALE_REQUEST_LIMIT, 60000);

		try
		{
			String factoryKey = getFactoryKeyForCapabilities(caps);
			Factory factory = (Factory) WorldWind
					.createConfigurationComponent(factoryKey);
			return factory.createFromConfigSource(caps, configParams);
		}
		catch (Exception e)
		{
			// Ignore the exception, and just return null.
		}

		return null;
	}

	protected static String getFactoryKeyForCapabilities(WMSCapabilities caps)
	{
		boolean hasApplicationBilFormat = false;

		Set<String> formats = caps.getImageFormats();
		for (String s : formats)
		{
			if (s.contains("application/bil"))
			{
				hasApplicationBilFormat = true;
				break;
			}
		}

		return hasApplicationBilFormat ? AVKey.ELEVATION_MODEL_FACTORY
				: AVKey.LAYER_FACTORY;
	}

	protected static String makeTitle(WMSCapabilities caps, LayerInfo layerInfo)
	{
		String layerNames = layerInfo.params.getStringValue(AVKey.LAYER_NAMES);
		String styleNames = layerInfo.params.getStringValue(AVKey.STYLE_NAMES);
		String[] lNames = layerNames.split(",");
		String[] sNames = styleNames != null ? styleNames.split(",") : null;

		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < lNames.length; i++)
		{
			if (sb.length() > 0) sb.append(", ");

			String layerName = lNames[i];
			WMSLayerCapabilities lc = caps.getLayerByName(layerName);
			String layerTitle = lc.getTitle();
			sb.append(layerTitle != null ? layerTitle : layerName);

			if (sNames == null || sNames.length <= i) continue;

			String styleName = sNames[i];
			WMSLayerStyle style = lc.getStyleByName(styleName);
			if (style == null) continue;

			sb.append(" : ");
			String styleTitle = style.getTitle();
			sb.append(styleTitle != null ? styleTitle : styleName);
		}

		return sb.toString();
	}

	protected void makeProgressPanel()
	{
		// Create the panel holding the progress bar during loading.

		JPanel outerPanel = new JPanel(new BorderLayout());
		outerPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
		outerPanel.setPreferredSize(this.size);

		JPanel innerPanel = new JPanel(new BorderLayout());
		innerPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
		JProgressBar progressBar = new JProgressBar();
		progressBar.setIndeterminate(true);
		innerPanel.add(progressBar, BorderLayout.CENTER);

		JButton cancelButton = new JButton("Cancel");
		innerPanel.add(cancelButton, BorderLayout.EAST);
		cancelButton.addActionListener(new AbstractAction()
		{
			public void actionPerformed(ActionEvent actionEvent)
			{
				if (loadingThread.isAlive()) loadingThread.interrupt();

				Container c = SmartScopeWMSLayersPanel.this.getParent();
				c.remove(SmartScopeWMSLayersPanel.this);
			}
		});

		outerPanel.add(innerPanel, BorderLayout.NORTH);
		this.add(outerPanel, BorderLayout.CENTER);
		this.revalidate();
	}
}
数据下载地址: http://download.csdn.net/detail/liushuo_whu/8426723

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页