SuperMap iClient for Leaflet
开发入门
下面将以SuperMap iServer 发布的World地图为例,介绍如何使用SuperMap iClient for JavaScript 来创建一个简单的地图应用。
第一步:下载并解压产品包
下载 SuperMap iClient for JavaScript 源码或压缩包文件,解压文件于本地磁盘。
第二步:创建 HTML 显示页面
在磁盘上任意位置新建文件夹并自定义该文件夹,本例命名为“MyFirst”;在 “MyFirst”文件夹下用文本编辑工具(如NotePad++)新建一个“GettingStarted.html”的 Html 页面,注意将该Html页面保存为 UTF-8 编码格式,并添加入以下代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SuperMap REST 地图服务底图</title>
</head>
<body style=" margin: 0;overflow: hidden;background: #fff;width: 100%;height:100%;position: absolute;top: 0;">
<div id="map" style="margin:0 auto;width: 100%;height: 100%"></div>
</body>
</html>
第三步:引用资源文件
拷贝iclient9-leaflet.js文件夹到“MyFirst”文件夹下。
第四步:引入leaflet.js,leaflet.css, iclient9-leaflet.js
<head>
<meta charset="UTF-8">
<title>SuperMap REST 地图服务底图</title>
<link rel="stylesheet" href="https://cdn.bootcss.com/leaflet/1.0.3/leaflet.css">
<script type="text/javascript" src="https://cdn.bootcss.com/leaflet/1.0.3/leaflet.js"></script>
<script type="text/javascript" src="./iclient9-leaflet.min.js"></script>
</head>
第五步:<body>之间添加如下代码,实现创建地图应用功能
<body style=" margin: 0;overflow: hidden;background: #fff;width: 100%;height:100%;position: absolute;top: 0;">
<div id="map" style="margin:0 auto;width: 100%;height: 100%"></div>
<script type="text/javascript">
var map, url = "https://iserver.supermap.io/iserver/services/map-world/rest/maps/World";
map = L.map('map', {
crs: L.CRS.EPSG4326,
center: [0, 0],
maxZoom: 18,
zoom: 1
});
L.supermap.tiledMapLayer(url).addTo(map);
</script>
</body>
第六步:运行 GettingStarted.html 文件,浏览地图数据
运行效果

投影
SuperMap iClient for Leaflet 通过投影类 L.Proj.CRS 可以方便的定义地图投影,支持设置范围,原点,比例尺数组,分辨率数组。例如:
var crs = L.Proj.CRS("EPSG:4326", {
origin: [114.59, 42.31],
scaleDenominators: [100000, 50000, 25000, 20000, 10000, 5000, 2000, 1000, 500, 200, 100, 50, 20, 1]
});
map = L.map('map', {
crs: crs,
center: [39.79, 116.85],
});
L.supermap.tiledMapLayer(url).addTo(map);
查看源码 »
对于不支持或者用户自定义的投影,需要通过Proj4js.defs[]静态常量定义键值对实现。Proj4js 是一个投影相关的JavaScript 脚本库,详细介绍请参见 Proj4js 官网,地址如下:https://trac.osgeo.org/proj4js/。
目前 Proj4js 支持的投影种类有:WGS84, EPSG:4326, EPSG:4269, EPSG:3875, EPSG:3785, EPSG4139,EPSG:4181, EPSG:4272, EPSG:4302, EPSG:21781, EPSG:102113,EPSG:26591,EPSG:26912, EPSG:27200, EPSG:27563, EPSG:41001, EPSG:42304,EPSG:102067, EPSG:102757, EPSG:102758, EPSG:900913, GOOGLE
Proj4js.defs("EPSG:21418","+proj=tmerc +lat_0=0 +lon_0=105 +k=1 +x_0=18500000 +y_0=0 +ellps=krass +units=m +no_defs ");
有关各种投影的参数定义,可参考https://spatialreference.org;如果已有定义,可搜索并查看其投影参数,例如EPSG:21418,其投影参数为https://spatialreference.org/ref/epsg/21418/proj4/。
对于用户自定义投影,可通过定义EPSGCODE和defs来创建投影,defs内容为参考投影参数,其分别代表了名称、投影、转换到wgs84坐标系(三参数)、椭球长半轴、扁率、原点纬线、中央经线、两条标准纬线、东偏移量、北偏移量、单位等。
Proj4js.defs("EPSG:10010","+title=Beijing1954 +proj=lcc +towgs84=0.0000,0.0000,0.0000 +a=6378245.0000 +rf=298.3 +lat_0=0.00000000 +lon_0=104.000000000 +lat_1=24.000000000 +lat_2=40.000000000 +x_0=0.000 +y_0=0.000 +units=m +no_defs");
兼容ie8
为更好的兼容 ie8,除了引入 leaflet.js、iclient9-leaflet.js,还需引入 polyfill。
可直接下载polyfill-ie8.js,也可引用在线地址: https://cdn.polyfill.io/v2/polyfill.min.js?features=default-3.3&excludes=Event。
在引入 leaflet.js 的 <script> 标签前加入下面代码:
<!--[if lte IE 8]>
<script src="your polyfill js"></script>
<![endif]-->
使用地图服务
SuperMap iClient for Leaflet提供的REST地图服务功能包含:
- 地图图层,支持动态图层定位、动态图层叠加
- 地图控件,如地图拖拽、平移缩放、绘制要素、缓存切换等
- 专题图,包括单值专题图、范围分段专题图、标签专题图、点密度专题图、等级符号专题图、统计专题图
- 查询,包括距离查询、几何对象查询、SQL查询、范围查询、海图查询
- 量算,支持距离和面积量算
使用REST地图服务示例
动态图层叠加
图层用来承载地图信息的显示。地图可以添加一个或者多个图层,组合显示达到用户所需要的最终效果。使用addTo()方法可以添加图层到map上。本示例为:添加京津地区地图到World地图上:
//初始化地图信息
var map = L.map('map', {
crs: L.CRS.EPSG4326,
center: [40, 118],
maxZoom: 18,
zoom: 6
});
//初始化图层
var layerWorld = L.supermap.tiledMapLayer(DemoURL.world);
var layerJingjin = L.supermap.tiledMapLayer(DemoURL.jingjin_map, {
transparent: true,
opacity: 0.6
});
//加载图层
layerWorld.addTo(map);
layerJingjin.addTo(map);
运行效果

距离量算
构建服务参数类
量算服务参数类提供服务请求所需的信息,该类提供量算的查询参数封装,提供的参数有geometry和unit,用来定义量算的几何对象和单位,代码如下:
var measureParam = new SuperMap.MeasureParameters();
//设置要量算的矢量对象({Line}或{Polygon}),geometry可以通过直接初始化的方法获取
measureParam.geometry = geometry;
measureParam.unit = SuperMap.Unit.METER;
构建服务类并发送请求
量算服务类负责向服务端发送请求,并将查询结果返回。使用服务类需要指定服务URL等服务参数,向服务端发送请求信息,然后通过监听服务请求完成事件,从事件服务数据类中获取最终的结果Result对象,按照用户需求进行处理,代码如下:
//初始化服务类,设置服务请求关键参数
var measureService = L.supermap.measureService(URL);
//提交服务请求,传递服务查询参数,获取返回结果并按照用户需求进行处理
measureService.measureDistance(measureParam, function (serviceResult){
function doSomething(serviceResult);
});
3.处理结果
在服务请求事件的处理过程中,我们可以获取结果信息并予以展示,下面使用弹窗的形式展示量算结果:
function doSomething(serviceResult) {
var distance = serviceResult.result.distance,
unit = serviceResult.result.unit;
var content = "距离: " + distance + “ ”+unit;
//在起始点marker上添加弹窗
marker.bindPopup(content).openPopup(marker.getLatLng());
}
运行效果

使用OGC地图服务示例
WMS服务
使用WMS图层,可以访问基于OGC WMS标准实现图层服务,包括iServer以外的其他第三方WMS服务。WMS服务符合OGC(Open Geospatial Consortium,开放地理信息联盟)制定的WMS实现规范,目前为1.1.1和1.3.0版本。
本节将以SuperMap iServer服务器默认发布的”WMS_China”为例,介绍添加WMS图层,显示OGC地图服务的地图数据
//初始化地图
var url = "https://iserver.supermap.io/iserver/services/map-china400/wms111/China";
var map = L.map('map', {
center: [0, 0],
maxZoom: 18,
zoom: 1
});
//初始化图层
var layer =L.tileLayer.wms(url, {
layers: 'China',
format: 'image/png',
transparent: true,
noWrap: true,
});
//加载图层
layer.addTo(map);
运行效果

WMTS服务
使用WMTS图层,可以访问基于OGC WMTS 1.0.0 标准实现图层服务,包括iserver以外的其他第三方WMTS服务。WMTS是OGC提出的首个支持REST的服务标准,目前为 1.0.0 版本,该服务支持三种请求模式:HTTP KVP(Key-Value Pair)方式、SOAP方式、REST方式。注意事项:WMTS对接更为广泛的服务,要求用户必须设置出图请求所需的各类参数:matrixIds、layer、tilematrixSet、url等,其中matrixIds会因为服务和出图依照的标准比例尺集不同而有所差异,需根据情况自行设置。
本节将以SuperMap iServer服务器默认发布的“China_WMTS”服务为例,介绍WMTS服务的使用。
//初始化地图
//当前图层的分辨率数组信息
var res = [];
for (var i = 0; i < 22; i++) {
res.push(165664.43905455674 / (Math.pow(2, i)));
}
var map = L.map('map', {
center: [0, 0],
maxZoom: 18,
zoom: 0,
crs: L.Proj.CRS("EPSG:3857", '',
{
origin: [-2.0037508342789244E7, 2.0037508342789244E7],
resolutions: res,
bounds: L.bounds([-2.0037508342789244E7, -2.0037508342789244E7], [2.0037508342789244E7, 2.0037508342789244E7])
})
});
//初始化图层
var url = "https://iserver.supermap.io/iserver/services/map-china400/wmts100";
var layer = L.supermap.wmtsLayer(url,
{
layer: "China",
style: "default",
tilematrixSet: "Custom_China",
format: "image/png"
});
//加载图层
layer.addTo(map);
运行效果

使用数据服务
SuperMap iClient for Leaflet支持的REST数据服务包括:
- 数据集ID查询
- 数据集几何查询
- 数据集缓冲区查询
- 数据集SQL查询
- 数据集编辑
使用REST数据服务示例
数据集ID查询
数据集ID查询,即在数据集中查询符合指定ID的地理空间要素,并在客户端中展示出来。本示例为:在World数据服务中查询指定ID的要素:
//初始化地图,并为地图添加事件
var baseUrl = "https://iserver.supermap.io/iserver/services/map-world/rest/maps/World";
var map = L.map('map', {
preferCanvas: true,
crs: L.CRS.EPSG4326,
center: [20, 80],
maxZoom: 18,
zoom: 2
});
L.supermap.tiledMapLayer(baseUrl).addTo(map).on("load", function () {
query();
});
//数据集ID查询处理
function query() {
//数据集ID查询服务参数
var idsParam = new SuperMap.GetFeaturesByIDsParameters({
IDs: [246, 247],
datasetNames: ["World:Countries"]
});
//向服务器发送请求,并对返回的结果进行处理
var url = "https://iserver.supermap.io/iserver/services/data-world/rest/data";
L.supermap.featureService(url).getFeaturesByIDs(idsParam, function (serviceResult) {
L.geoJSON(serviceResult.result.features, {
onEachFeature: function (feature, layer) {
//为结果添加点击弹窗事件
layer.bindPopup("ID: " + feature.properties.SMID +
"<br>" + "国家:" + feature.properties.COUNTRY);
}}).addTo(map);
});
}
运行效果

数据集SQL查询
数据集SQL查询,即在指定数据集集合中查找符合 SQL 条件的矢量要素,并在客户端中展示出来。本示例为:在World数据服务中查询指定SMID的要素:
//初始化地图,并为地图添加事件
var baseUrl = "https://iserver.supermap.io/iserver/services/map-world/rest/maps/World",
var map = L.map('map', {
preferCanvas: true,
crs: L.CRS.EPSG4326,
center: [0, 0],
maxZoom: 18,
zoom: 1
});
L.supermap.tiledMapLayer(baseUrl).addTo(map).on("load", function () {
query();
});
//数据集SQL查询处理
function query() {
//数据集SQL查询服务参数
var sqlParam = new SuperMap.GetFeaturesBySQLParameters({
queryParameter: {
name: "Countries@World",
attributeFilter: "SMID = 247"
},
datasetNames: ["World:Countries"]
});
//向服务器发送请求,并对返回的结果进行处理
var url = "https://iserver.supermap.io/iserver/services/data-world/rest/data";
L.supermap.featureService(url).getFeaturesBySQL(sqlParam, function (serviceResult) {
//在地图上显示查询结果,并为结果添加弹窗
L.geoJSON(serviceResult.result.features).addTo(map).bindPopup('SMID = 247');
});
}
运行效果

使用空间分析服务
SuperMap iClient for Leaflet支持的空间分析功能包括:
- 缓冲区分析
- 叠加分析
- 表面分析
- 动态分段
- 点定里程
- 里程定点
- 里程定线
示例:缓冲区分析
缓冲区分析(buffer)是根据指定的距离在点、线和多边形实体周围自动建立一定宽度的区域范围的分析方法。例如,在环境治理时,常在污染的河流周围划出一定宽度的范围表示受到污染的区域;又如在飞机场,常根据健康需要在周围划分出一定范围的区域作为非居住区等。
下面以长春数据为例,对“团结路”进行半径为10米的圆头缓冲分析,缓冲区分析的接口使用方法如下:
设置缓冲区分析参数、缓冲区通用参数。
//缓冲区分析参数
dsBufferAnalystParams = new SuperMap.DatasetBufferAnalystParameters({
//用来做缓冲区分析的数据源中数据集名称
dataset: "RoadLine2@Changchun",
//设置数据集中集合对象的过滤条件
filterQueryParameter: new SuperMap.FilterParameter({
//属性过滤条件
attributeFilter: "NAME='团结路'"
}),
//缓冲区分析通用参数设置
bufferSetting: new SuperMap.BufferSetting({
//缓冲区端点枚举值,包含FLAT和ROUND
endType: SuperMap.BufferEndType.ROUND,
//左侧缓冲距离
leftDistance: {value: 10},
//右侧缓冲距离
rightDistance: {value: 10},
//圆头缓冲圆弧处线段的个数
semicircleLineSegment: 10
})
});
设置缓冲区分析服务对象,用于将客户端设置的缓冲区分析服务参数传递给服务端,并接收服务端返回的缓冲区分析结果数据。当向服务端发送请求并且服务端成功返回结果时,用户可对获得的缓冲区分析结果做相应处理。
//初始化地图,并为地图添加事件
var baseUrl = "https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/长春市区图";
var map = L.map('map', {
crs: L.CRS.NonEarthCRS({
bounds: L.bounds([48.4, -7668.25], [8958.85, -55.58]),
origin: L.point(48.4, -55.58)
}),
center: [-3375, 5105],
maxZoom: 18,
zoom: 6
});
L.supermap.tiledMapLayer(baseUrl, {noWrap: true}).addTo(map).on("load", function () {
bufferAnalystProcess();
});
//定义缓冲区分析服务
function bufferAnalystProcess(){
var serviceUrl = "https://iserver.supermap.io/iserver/services/spatialanalyst-changchun/restjsr/spatialanalyst"
var bufferServiceByDatasets = L.supermap.spatialAnalystService(serviceUrl);
//向服务端发送服务请求,并对返回的结果进行处理后显示在地图上
bufferServiceByDatasets.bufferAnalysis(dsBufferAnalystParams,function(serviceResult)
{
var result = serviceResult.result;
resultLayer = L.geoJSON(result.recordset.features, {color: "red"});
resultLayer.addTo(map);
});
}
运行效果

示例:叠加分析
叠加分析是GIS中的一项非常重要的空间分析功能,是指在统一空间参考系统下,通过对两个数据集进行的一系列集合运算,产生新数据集的过程,其目的是通过对空间数据的加工或分析,提取用户需要的新的空间几何信息。同时,通过叠加分析,还将对数据的各种属性信息进行处理。
目前叠加分析广泛应用于资源管理、城市建设评估、国土管理、农林牧业、统计等领域。叠加分析在各领域中的作用:
- 资源管理主要应用于农业和林业领域,解决农业和林业领域各种资源(如土地、森林、草场等)分布变化、统计等问题
- 城市建设评估主要应用于分析城市人口、经济、建设等的发展变化,统计变化趋势和变化规律
- 土地和地籍管理涉及土地使用性质变化、地块轮廓变化、地籍权属关系变化等许多内容,借助GIS的叠加分析功能可以高效、高质量地完成这些工作
- 生态、环境的管理评价用于区域生态规划的评价、环境现状评价、环境影响评价、污染物削减分配的决策支持等
- 地学研究与应用用于地形分析、流域分析、土地利用研究、经济地理研究、空间统计分析、制图等都可以借助叠加分析来完成/li>
下面将京津地区的行政区域与临边地区的行政区域进行叠加分析,叠加分析接口使用方法如下所示:
设置叠加分析参数
//设置叠加分析参数
var dsOverlayAnalyParams = new SuperMap.DatasetOverlayAnalystParameters({
sourceDataset: "BaseMap_R@Jingjin", //叠加分析中源数据集的名称
operateDataset: "Neighbor_R@Jingjin", //叠加分析中操作数据集名称
tolerance: 0, //容限
operation: SuperMap.OverlayOperationType.UNION //叠加分析操作类型
});
设置叠加分析服务对象,用于将客户端设置的叠加分析服务参数传递给服务端,并接收服务端返回的分析结果数据。当向服务端发送请求并且服务端成功返回结果时,用户可对获得的叠加分析结果做相应处理。
//初始化地图,并为地图设置事件
var baseUrl = "https://iserver.supermap.io/iserver/services/map-jingjin/rest/maps/京津地区人口分布图_专题图",
var map = L.map('map', {
crs: L.CRS.EPSG4326,
center: [40.05, 116.85],
maxZoom: 18,
zoom: 6
});
L.supermap.tiledMapLayer(baseUrl, { transparent: true, cacheEnabled: false, noWrap: true}).addTo(map) .on("load", function () {
overlayAnalystProcess();
});
//定义叠加分析服务
function overlayAnalystProcess() {
var serviceUrl = "https://iserver.supermap.io/iserver/services/spatialanalyst-sample/restjsr/spatialanalyst";
var overlayAnalystService = L.supermap.spatialAnalystService(serviceUrl);
//向服务端发送服务请求,并对返回的结果进行处理后显示在地图上
overlayAnalystService.overlayAnalysis(dsOverlayAnalyParams, function(serviceResult) {
var result = serviceResult.result;
var resultLayer = L.geoJSON(result.recordset.features);
resultLayer.addTo(map);
);
}
运行效果

示例:表面分析
表面分析是指通过对数据集或几何对象进行分析,从中挖掘原始数据所包含的隐藏信息。表面分析包括提取等值线和提取等值面。等值线是将相邻的、具有相同值的点连起来的线,常用的等值线有等高线、等深线、等温线、等压线、等降水量线等。等值线的分布反应了栅格表面上值的变化,等值线分布越密集的地方,表示栅格表面值的变化比较剧烈。等值线分布较稀疏的地方,表示栅格表面值的变化较小。通过提取等值线,可以找到高程、温度、降水量等值相同的位置,同时等值线的分布状况也可以反映出变化的陡峭和平缓区。等值面是由相邻的等值线封闭组成的面,等值面的变化可以很直观的表示出相邻等值线之间的变化,诸如高程、降水、温度或大气压力等。通过提取等值面可以获得高程、降水、温度等值相同的地方。
本节将通过从全国平均气温采样点中提取等值线的功能来具体说明表面分析的接口使用。
设置表面分析参数设置参数、数据集表面分析——等值线提取参数
//剪裁区域设置
var region = L.polygon([[4010338,0],[4010338,1063524],[3150322,1063524],[3150322,0]]);
//表面分析参数设置
var extractParams = new SuperMap.SurfaceAnalystParametersSetting({
datumValue: 0, //表面分析中提取等值线基准值
interval: 2, //等值距,两条等值线之间的间隔值
resampleTolerance: 0, //重采样容限
smoothMethod: SuperMap.SmoothMethod.BSPLINE, //光滑处理所使用的方法
smoothness: 3, //等值线的光滑度
clipRegion: region //裁剪对象
});
//表面分析提取操作参数
var surfaceAnalystParams = new SuperMap.DatasetSurfaceAnalystParameters({
extractParameter: extractParams, //表面分析参数
dataset: "SamplesP@Interpolation", //叠加分析中源数据集名称
resolution: 3000, //中间结果分辨率
zValueFieldName: "AVG_TMP" //用于提取操作的字段名称
});
设置表面分析服务对象,用于将客户端设置的表面分析服务参数传递给服务端, 并接收服务端返回的表面分析结果数据。当向服务端发送请求并且服务端成功返回结果时,用户可对获得的表面分析结果做相应处理。
//初始化地图,并为地图添加事件
var baseUrl = "https://iserver.supermap.io/iserver/services/map-temperature/rest/maps/全国温度变化图";
var map = L.map('map', {
crs: L.CRS.NonEarthCRS({
bounds: L.bounds([-2640403.63, 1873792.1], [3247669.39, 5921501.4]),
origin: L.point(-2640403.63, 5921501.4)
}),
center: [3580330, 531762],
maxZoom: 18,
zoom: 2
});
L.supermap.tiledMapLayer(baseUrl, {noWrap: true}).addTo(map).on("load", function () {
surfaceAnalystProcess();
});
//表面分析服务处理
function surfaceAnalystProcess() {
//初始化表面分析服务实例
var serviceUrl = "https://iserver.supermap.io/iserver/services/spatialanalyst-sample/restjsr/spatialanalyst" ;
var surfaceAnalystService = L.supermap.spatialAnalystService(serviceUrl);
//向服务端发送请求,并对返回的结果进行处理
surfaceAnalystService.surfaceAnalysis(surfaceAnalystParams, function (serviceResult) {
L.geoJSON(serviceResult.result.recordset.features, {weight: 3}).addTo(map);
});
}
运行效果

示例:动态分段
动态分段技术是在传统GIS数据模型的基础上,利用线性参考技术,实现属性数据在地图上动态地显示、分析及输出等,是GIS空间分析中的一个重要技术手段。它不是在线要素沿线上某种属性发生变化的地方进行“物理分段”,而是在传统的GIS数据模型的基础上利用线性参考系统的思想及算法,将属性的沿线变化存储为独立的属性表字段(事件属性表);在分析、显示、查询和输出时直接依据事件属性表中的距离值对线性要素进行动态逻辑分段,使用相对位置描述发生在线上的事件,比传统GIS要素更容易定位。除此之外,该技术还提高了数据制作效率和数据存储空间利用率,降低了数据维护的复杂度。目前已广泛应用于公共交通管理、路面质量管理、航海线路模拟、通讯网络管理、电网管理等诸多领域。
本专题将以长春市道路的数据为例,根据某一时刻的某些道路路段出现拥堵和车辆较多现象,利用动态分段技术在客户端实时动态显示出道路的路况(拥挤/缓行/畅通),以提示驾驶人员避免进入拥堵路段,选择合适的行驶路线。动态分段接口使用方法如下:
在客户端设置用于向服务端发送的动态分段各参数,包括数据返回选项(DataReturnOption)、动态分段参数(generateSpatialDataParams)
//配置动态分段参数
var generateSpatialDataParams = new SuperMap.GenerateSpatialDataParameters({
routeTable: "RouteDT_road@Changchun",//路由数据集
routeIDField: "RouteID",//路由数据集的标识字段,即路由ID
eventTable: "LinearEventTabDT@Changchun",//用于生成空间数据的事件表名
eventRouteIDField: "RouteID",//用于生成空间数据的事件表的路由标识字段
measureField: "",//用于生成空间数据的事件表的刻度字段
measureStartField: "LineMeasureFrom",//事件表的起始刻度字段
measureEndField: "LineMeasureTo",//事件表的终止刻度字段
measureOffsetField: "",//刻度偏移量字段
errorInfoField: "",//错误信息字段
//设置数据返回选项
dataReturnOption: new SuperMap.DataReturnOption({
//设置返回的最大记录数
expectCount: 1000,
//设置结果数据集标识, 由于dataReturnMode设置为//SuperMap.REST.DataReturnMode.DATASET_ONLY,则返回数据集的名称
dataset: "generateSpatialData@Changchun",
//如果用户命名的结果数据集名称与已有的数据集重名, 则删除已有的数据集
deleteExistResultDataset: true,
//设置数据返回模式为DATASET_ONLY
dataReturnMode: SuperMap.DataReturnMode.DATASET_ONLY
})
});
定义动态分段服务对象,用于将客户端设置的动态分段分析服务参数(parameters)传递给服务端,并接收服务端返回的动态分段分析结果数据。当向服务端发送请求并且服务端成功返回结果时,用户可在客户端对获得的动态分段空间数据做相应处理,将空间数据中的路况信息以专题图的形式展现给用户。
//初始化地图,并为地图设置事件
var baseUrl = "https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/长春市区图",
var map = L.map('map', {
crs: L.CRS.NonEarthCRS({
bounds: L.bounds([48.4, -7668.25], [8958.85, -55.58]),
origin: L.point(48.4, -55.58)
}),
center: [-3861.911472192499, 4700],
maxZoom: 18,
zoom: 2
});
L.supermap.tiledMapLayer(baseUrl, {noWrap: true}).addTo(map).on("load", function () {
generateSpatialDataAnalystProcess();
});
//配置动态分段服务
function generateSpatialDataAnalystProcess(){
var serviceUrl = "https://iserver.supermap.io/iserver/services/spatialanalyst-changchun/restjsr/spatialanalyst"
var generateSpatialDataService = L.supermap.spatialAnalystService(serviceUrl);
//向服务端发送请求,并将返回的结果以专题图的形式展现在客户端
generateSpatialDataService.generateSpatialData(generateSpatialDataParams, function () {
//用专题图展示分析结果
showAnalysisResult_ThemeGridUnique();
});
//数据返回之后,会在客户端以单值专题图形式展现
function showAnalysisResult_ThemeGridUnique() {
//创建专题图服务实例
themeService = L.supermap.themeService(baseUrl);
//配置专题样式
var style1, style2, style3;
style1 = new SuperMap.ServerStyle({
fillForeColor: new SuperMap.ServerColor(242, 48, 48),
lineColor: new SuperMap.ServerColor(242, 48, 48),
lineWidth: 1
});
style2 = new SuperMap.ServerStyle({
fillForeColor: new SuperMap.ServerColor(255, 159, 25),
lineColor: new SuperMap.ServerColor(255, 159, 25),
lineWidth: 1
});
style3 = new SuperMap.ServerStyle({
fillForeColor: new SuperMap.ServerColor(91, 195, 69),
lineColor: new SuperMap.ServerColor(91, 195, 69),
lineWidth: 1
});
//配置专题项
var themeUniqueIteme1, themeUniqueIteme2, themeUniqueIteme3;
themeUniqueIteme1 = new SuperMap.ThemeUniqueItem({
unique: "拥挤",
style: style1
});
themeUniqueIteme2 = new SuperMap.ThemeUniqueItem({
unique: "缓行",
style: style2
});
themeUniqueIteme3 = new SuperMap.ThemeUniqueItem({
unique: "畅通",
style: style3
});
var themeUnique = new SuperMap.ThemeUnique({
uniqueExpression: "TrafficStatus",
defaultStyle: new SuperMap.ServerStyle({
fillForeColor: new SuperMap.ServerColor(48, 89, 14),
lineColor: new SuperMap.ServerColor(48, 89, 14)
}),
items: [themeUniqueIteme1, themeUniqueIteme2, themeUniqueIteme3]
});
themeParameters = new SuperMap.ThemeParameters({
themes: [themeUnique],
datasetNames: ["generateSpatialData"],
dataSourceNames: ["Changchun"]
});
themeService.getThemeInfo(themeParameters, function (serviceResult1) {
var result = serviceResult1.result;
if (result && result.newResourceID) {
themeLayer = L.supermap.tiledMapLayer(baseUrl, {
noWrap: true,
cacheEnabled: false,
transparent: true,
layersID: result.newResourceID
//opacity: 0.8
}).addTo(map);
}
});
}
运行效果

示例:点定里程
点定里程是计算路由上某点到起始点的M值,实际应用情景例如知道某事故发生的位置确定该点位于某路口距离。
下面以长春数据为例,计算一条路上(路由ID为1690的路由)发生交通事故的地点到该条路路口的距离。
点定里程接口使用方法如下:
在进行点定里程处理之前,需要先初始化地图。
//初始化地图,并为地图设置事件
var baseUrl = "https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/长春市区图";
var map = L.map('map', {
crs: L.CRS.NonEarthCRS({
bounds: L.bounds([48.4, -7668.25], [8958.85, -55.58]),
origin: L.point(48.4, -55.58)
}),
center: [-3861.91, 4503.62],
maxZoom: 18,
zoom: 2
});
L.supermap.tiledMapLayer(baseUrl, {noWrap: true}).addTo(map) .on("load", function () {
routeCalculateMeasureProcess();
});
地图加载完成后进行点定里程分析服务,首先根据RouteID获得路由对象,路由对象查询成功之后才能进行后续的点定里程操作。
function routeCalculateMeasureProcess() {
//设置SQL查询参数
var queryBySQLParams = new SuperMap.QueryBySQLParameters({
queryParams: [
new SuperMap.FilterParameter({
name: "RouteDT_road@Changchun",
attributeFilter: "RouteID=1690"
})
]
});
//创建SQL服务
var queryBySQLService = L.supermap.queryService(baseUrl);
//向服务器发送请求,并对返回的SQL查询结果数据进行处理
queryBySQLService.queryBySQL(queryBySQLParams, function (serviceResult) {
var resultLayer = L.geoJSON(serviceResult.result.recordsets[0].features,
{color: "red"}).addTo(map);
//将形成路由的点提出来,为了构造下面点定里程服务参数的sourceRoute
var pointsList = [];
var routeObj = serviceResult.result.recordsets[0].features.features[0].geometry.coordinates[0];
for (var i = 0; i < routeObj.length; i++) {
pointsList.push([routeObj[i][1], routeObj[i][0],routeObj[i][2]])
}
routeLine = L.polyline(pointsList);
//在组成路由的点中选取一个查询点(数组中第8个点),并添加到地图上
var marker= L.circleMarker([routeObj[7][1], routeObj[7][0]],
{radius: 3, color: 'black'}).addTo(map);
//创建点定里程服务
var serviceUrl = "https://iserver.supermap.io/iserver/services/spatialanalyst-changchun/restjsr/spatialanalyst";
var routeCalculateMeasureService = L.supermap.spatialAnalystService(serviceUrl);
//点定里程服务参数设置
var routeCalculateMeasureParameters = new SuperMap.RouteCalculateMeasureParameters({
"sourceRoute": routeLine,路由类型
"point": L.point(routeObj[7][0], routeObj[7][1]),//查询点
"tolerance": 10,
"isIgnoreGap": false
});
//向服务器发送请求,并对返回的结果数据进行处理 routeCalculateMeasureService.routeCalculateMeasure ( routeCalculateMeasureParameters, function (serviceResult) {
//为查询结果添加弹窗,显示获取到的M值
marker.bindTooltip("查询获取的M值为:" + serviceResult.result.measure + "", {direction:"top",offset:L.point(0,-5)}).openTooltip();
});
});
}
运行效果

示例:里程定点
里程定点是根据指定路由上的M值来定位点。应用情景与点定里程相反,如知道某事故距离某路口位置,需要确定其相对精确的坐标的时候使用。
下面以长春数据为例,确定一条发生交通事故的路上(路由ID为1690的路由)与路口距离为10km的事故点,里程定点的接口使用方法:
在进行里程定点处理之前,需要先初始化地图。
//初始化地图,并为地图添加事件
var baseUrl = "https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/长春市区图";
var map = L.map('map', {
crs: L.CRS.NonEarthCRS({
bounds: L.bounds([48.4, -7668.25], [8958.85, -55.58]),
origin: L.point(48.4, -55.58)
}),
center: [-3861.91, 4503.62],
maxZoom: 18,
zoom: 2
});
L.supermap.tiledMapLayer(baseUrl, {noWrap: true}).addTo(map) .on("load", function () {
routeLocatorProcess();
});
地图加载完成后进行里程定点分析服务,首先根据RouteID获得路由对象,路由对象查询成功之后才能进行后续的里程定点操作。
function routeLocatorProcess() {
//SQL查询服务参数设置
queryBySQLParams = new SuperMap.QueryBySQLParameters({
queryParams: [
new SuperMap.FilterParameter({
name: "RouteDT_road@Changchun",
attributeFilter: "RouteID=1690"
})
]
});
//创建查询服务
var queryBySQLService = L.supermap.queryService(baseUrl);
//向服务器发送请求进行SQL查询,并将返回的结果进行处理展现在地图上
queryBySQLService.queryBySQL(queryBySQLParams, function (serviceResult) {
var resultLayer = L.geoJSON(serviceResult.result.recordsets[0].features,
{color: "red"}).addTo(map);
//将形成路由的点提出来,为了构造下面里程定点服务sourceRoute属性的polyline
var pointsList = [];
var routeObj = serviceResult.result.recordsets[0].features.features[0].geometry.coordinates[0];
for (var i = 0; i < routeObj.length; i++) {
pointsList.push([routeObj[i][1], routeObj[i][0], routeObj[i][2]])
}
var routeLine = L.polyline(pointsList);
//里程定点服务处理
//里程定点参数设置
var routeLocatorParams_point = new SuperMap.RouteLocatorParameters({
"sourceRoute": routeLine, //路由对象
"type": "POINT", //类型,点或线
"measure": 200, //里程值
"offset": 0, //定位点偏移量
"isIgnoreGap": true //是否忽略子对象之间的距离
});
//创建空间分析服务
var serviceUrl =
"https://iserver.supermap.io/iserver/services/spatialanalyst-changchun/restjsr/spatialanalyst";
var routeLocatorService = L.supermap.spatialAnalystService(serviceUrl);
//向服务器发送请求进行里程定点服务分析,并将返回的结果进行处理展现在客户端上
routeLocatorService.routeLocate(routeLocatorParams_point, function (serviceResult) {
var layer=L.geoJSON(serviceResult.result.resultGeometry).addTo(map);
//添加弹窗
layer.bindTooltip("查询到的里程为 " + routeLocatorParams_point.measure + " 的点" , {direction:"top", offset:L.point(0,-5)}).openTooltip();
});
});
}
运行效果

示例:里程定线
里程定线是根据指定线的范围来确定路由上对应的线对象。应用场景如当知道某一路段发生阻塞,能够确定该路段相对精确的位置范围。
下面以长春数据为例,一条路(路由ID为1690的路由)在距离路口10-800km之间的发生堵塞,里程定线的接口使用方法如下:
在进行里程定线处理之前,需要先初始化地图。
//初始化地图,并为地图添加事件
var baseUrl =
"https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/长春市区图",
var map = L.map('map', {
crs: L.CRS.NonEarthCRS({
bounds: L.bounds([48.4, -7668.25], [8958.85, -55.58]),
origin: L.point(48.4, -55.58)
}),
center: [-3861.91, 4503.62],
maxZoom: 18,
zoom: 2
});
L.supermap.tiledMapLayer(baseUrl, {noWrap: true}).addTo(map) .on("load", function () {
routeLocatorProcess();
});
地图加载完成后进行里程定线分析服务,首先根据RouteID获得路由对象,路由对象查询成功之后才能进行后续的里程定线操作。
function routeLocatorProcess () {
//SQL查询服务参数设置
queryBySQLParams = new SuperMap.QueryBySQLParameters({
queryParams: [
new SuperMap.FilterParameter({
name: "RouteDT_road@Changchun",
attributeFilter: "RouteID=1690"
})
]
});
//创建查询服务
var queryBySQLService = L.supermap.queryService(baseUrl);
//向服务器发送请求进行SQL查询,并将返回的结果进行处理展现在地图上
queryBySQLService.queryBySQL(queryBySQLParams, function (serviceResult) {
var resultLayer = L.geoJSON(serviceResult.result.recordsets[0].features,
{color: "red"}).addTo(map);
//将形成路由的点提出来,为了构造下面里程定点服务sourceRoute属性的polyline
var pointsList = [];
var routeObj = serviceResult.result.recordsets[0].features.features[0].geometry.coordinates[0];
for (var i = 0; i < routeObj.length; i++) {
pointsList.push([routeObj[i][1], routeObj[i][0], routeObj[i][2]])
}
var routeLine = L.polyline(pointsList);
//里程定线服务处理
//里程定线参数设置
var routeLocatorParams_line = new SuperMap.RouteLocatorParameters({
"sourceRoute": routeLine, //路由对象
"type": "LINE", //类型,点或线
"startMeasure": 10, //定位线的起始M值
"endMeasure": 800, //定位线的终止M值
"isIgnoreGap": true //是否忽略子对象之间的距离
});
//创建空间分析服务
var serviceUrl =
"https://iserver.supermap.io/iserver/services/spatialanalyst-changchun/restjsr/spatialanalyst";
var routeLocatorService = L.supermap.spatialAnalystService(serviceUrl);
//向服务器发送请求进行里程定线服务分析,并将返回的结果进行处理展现在客户端上
routeLocatorService.routeLocate(routeLocatorParams_line, function (serviceResult) {
var resultLayer1 = L.geoJSON(serviceResult.result.resultGeometry).addTo(map);
})
}
运行效果

使用交通网络分析服务
SuperMap iClient for Leaflet支持的交通网络分析REST服务包含:
- 最佳路径分析
- 服务区分析
- 旅行商分析
- 最近设施查找分析
- 选址分区分析
- 多旅行商分析
示例:最佳路径分析
最佳路径,是求解网络中两点之间阻抗最小的路经,必须按照结点的选择顺序访问网络中的结点。“阻抗最小”有多种理解,如基于单因素考虑的时间最短、费用最低、风景最好、路况最佳、过桥最少、收费站最少、经过乡村最多等。
下面以长春数据为例,计算地图中将要行走的地点间的最佳路径。其接口使用方法如下:
设置最佳路径分析参数findPathParams,包括交通网络分析通用参数、途径站点等;
//交通网络分析结果参数
var resultSetting = new SuperMap.TransportationAnalystResultSetting({
returnEdgeFeatures: true, //是否在分析结果中包含弧段要素集合
returnEdgeGeometry: true, //返回的弧段要素集合中是否包含集合对象信息
returnEdgeIDs: true, //返回的结果中是否包含经过弧段ID集合
returnNodeFeatures: true, //返回的分析结果总是否包含结点要素集合
returnNodeGeometry: true, //返回的结点要素集合中是否包含集合对象信息
returnNodeIDs: true, //返回的分析结果中是否包含经过结点ID集合
returnPathGuides: true, //返回分析结果中是否包含行驶导引集合
returnRoutes: true//返回结果中是否包含路由对象集合
});
//交通网络分析通用参数
var analystParameter = new SuperMap.TransportationAnalystParameter({
resultSetting: resultSetting, //分析结果返回的内容
weightFieldName: "length"//阻力字段的名称
});
//最佳路径分析参数
var findPathParams = new SuperMap.FindPathParameters({
isAnalyzeById: false, //是否通过结点ID指定路径分析的结点
//最佳路径分析经过的结点或设施点数组
nodes: [L.latLng(-3000, 4000), L.latLng(-2500, 5500), L.latLng(-4000, 6900)],
hasLeastEdgeCount: false, //是否按照弧段数最少的进行最佳路径分析
parameter: analystParameter//交通网络分析通用参数
});
向服务端提交最佳路径分析的请求,待服务端成功处理并返回最佳路径分析结果serviceResult对其进行解析,将行驶路线在地图中展现出来并给出行驶导引信息。
//初始化地图,并为地图添加事件
var baseUrl = "https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/长春市区图";
var map = L.map('map', {
crs: L.CRS.NonEarthCRS({
bounds: L.bounds([48.4, -7668.25], [8958.85, -55.58]),
origin: L.point(48.4, -55.58)
}),
center: [-3600, 5000],
maxZoom: 18,
zoom: 2
});
L.supermap.tiledMapLayer(baseUrl, {noWrap: true}).addTo(map).on("load", function () {
findPathProcess();
});
//定义最佳路径分析服务
function findPathProcess(){
//添加站点
var marker1 = L.marker([-3000, 4000]).addTo(map);
marker1.bindPopup("站点一");
var marker2 = L.marker([-2500, 5500]).addTo(map);
marker2.bindPopup("站点二");
var marker3 = L.marker([-4000, 6900]).addTo(map);
marker3.bindPopup("站点三");
//设置人物图标
var myIcon = L.icon({
iconUrl: "https://iserver.supermap.io/iserver/iClient/forJavaScript/examples/images/walk.png",
iconSize: [20, 20]
});
var serviceUrl = "https://iserver.supermap.io/iserver/services/transportationanalyst-sample/rest/networkanalyst/RoadNet@Changchun";
var findPathService = L.supermap.networkAnalystService(serviceUrl);
//向服务器发送请求,并对返回的结果进行分析处理,展示在客户端上
findPathService.findPath(findPathParams, function (serviceResult) {
var result = serviceResult.result;
result.pathList.map(function (result) {
L.polyline(result.route).addTo(map);
L.geoJSON(result.pathGuideItems, {
pointToLayer: function (geoPoints, latlng) {
L.marker(latlng, {icon: myIcon}).addTo(map);
}
}).addTo(map);
})
});
}
运行效果

示例:服务区分析
服务区分析是为网络上指定的服务中心点查找其服务范围。例如:为网络上某点计算其 30 分钟的服务区,则结果服务区内,任意点出发到该点的时间都不会超过30分钟。
下面以长春数据为例,然后在地图中选择将要分析的服务中心点(支持多中心),根据选择服务中心点的顺序依次按照 400、500、600...递增的数值作为服务半径进行缓冲区分析。(即第一个服务中心点的服务半径为 400,第二个服务中心店的服务半径为 500,依次类推)
服务区分析接口使用方法:
设置服务区分析参数findServiceAreasParams,包括交通网络分析通用参数、途径站点等
//添加中心点
var marker = L.marker([-3375, 5605]).addTo(map);
//交通网络分析结果参数
var resultSetting = new SuperMap.TransportationAnalystResultSetting({
returnEdgeFeatures: true,//是否在分析结果中包含弧段要素集合
returnEdgeGeometry: true,//返回的弧段要素集合中是否包含集合对象信息
returnEdgeIDs: true,//返回的结果中是否包含经过弧段ID集合
returnNodeFeatures: true,//返回的分析结果总是否包含结点要素集合
returnNodeGeometry: true,//返回的结点要素集合中是否包含集合对象信息
returnNodeIDs: true,//返回的分析结果中是否包含经过结点ID集合
returnPathGuides: true,//返回分析结果中是否包含行驶导引集合
returnRoutes: true//返回结果中是否包含路由对象集合
};
//交通网络分析通用参数
var analystParameter = new SuperMap.TransportationAnalystParameter({
resultSetting: resultSetting,//分析结果返回的内容
weightFieldName: "length"//阻力字段的名称
});
var findServiceAreasParams = new SuperMap.FindServiceAreasParameters({
centers: [marker.getLatLng()],// 服务站点数组
isAnalyzeById: false,// 是否通过节点ID指定路径分析的结点
parameter: analystParameter,// 交通网络分析通用参数。
weights: weightsArray//每个服务站点提供服务的阻力半径
});
定义服务区分析服务对象,用于将客户端设置的服务区分析服务参数(parameters)传递给服务端, 并接收服务端返回的动态分段分析结果数据。当向服务端发送请求并且服务端成功返回结果时,用户可对获得的服务区分析结果做相应处理。
//初始化地图,并为地图添加事件
var baseUrl = "https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/长春市区图";
var map = L.map('map', {
crs: L.CRS.NonEarthCRS({
bounds: L.bounds([48.4, -7668.25], [8958.85, -55.58]),
origin: L.point(48.4, -55.58)
}),
center: [-3500, 5200],
maxZoom: 18,
zoom: 3
});
L.supermap.tiledMapLayer(baseUrl, {noWrap: true}).addTo(map).on("load", function () {
findServiceAreas();
});
//定义服务区分析服务
function findServiceAreas() {
var serviceUrl = "https://iserver.supermap.io/iserver/services/transportationanalyst-sample/rest/networkanalyst/RoadNet@Changchun";
var service = L.supermap.networkAnalystService(serviceUrl);
var resultLayer = L.featureGroup().addTo(map);
parameter.weights = [400 + Math.random() * 100];
//向服务器发送请求,并对返回的结果进行处理
service.findServiceAreas(findServiceAreasParams, function (serviceResult) {
var result = serviceResult.result;
result.serviceAreaList.map(function (serviceArea) {
resultLayer.addLayer(L.geoJSON(serviceArea.serviceRegion));
});
});
}
运行效果

示例:旅行商分析
旅行商分析是查找经过指定一系列点的路径,旅行商分析是无序的路径分析。旅行商可以自己决定访问结点的顺序,目标是旅行路线阻抗总和最小(或接近最小)。
旅行商分析,如果指定了终止点,则旅行商必须最后一个访问终止点,而其他经过点的访问次序有旅行商自己决定。下面以长春数据为例,对地图中将要行走的地点进行旅行商分析,其接口使用方法如下:
设置旅行商分析参数findTSPPathsParams,包括交通网络分析通用参数、途径站点等
//交通网络分析结果参数
var resultSetting = new SuperMap.TransportationAnalystResultSetting({
returnEdgeFeatures: true,//是否在分析结果中包含弧段要素集合
returnEdgeGeometry: true,//返回的弧段要素集合中是否包含集合对象信息
returnEdgeIDs: true,//返回的结果中是否包含经过弧段ID集合
returnNodeFeatures: true,//返回的分析结果总是否包含结点要素集合
returnNodeGeometry: true,//返回的结点要素集合中是否包含集合对象信息
returnNodeIDs: true,//返回的分析结果中是否包含经过结点ID集合
returnPathGuides: true,//返回分析结果中是否包含行驶导引集合
returnRoutes: true//返回结果中是否包含路由对象集合
};
//交通网络分析通用参数
var analystParameter = new SuperMap.TransportationAnalystParameter({
resultSetting: resultSetting,//分析结果返回的内容
weightFieldName: "length"//阻力字段的名称
});
var findTSPPathsParams = new SuperMap.FindTSPPathsParameters ({
isAnalyzeById: false,//是否经过结点ID号来指定途径点
nodes: nodeArray,//旅行商分析途径点数组,可以是点的坐标数组或者点的ID数组
endNodeAssigned: false,//是否指定终止点
parameter: analystParameter//交通网络分析通用参数
});
定义服务区分析服务对象,用于将客户端设置的服务区分析服务参数传递给服务端, 并接收服务端返回的动态分段分析结果数据。当向服务端发送请求并且服务端成功返回结果时,用户可对获得的旅行商分析结果做相应处理。
//初始化地图,并为地图设置事件
var baseUrl = "https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/长春市区图";
var map = L.map('map', {
crs: L.CRS.NonEarthCRS({
bounds: L.bounds([48.4, -7668.25], [8958.85, -55.58]),
origin: L.point(48.4, -55.58)
}),
center: [-3600, 4700],
maxZoom: 18,
zoom: 2
});
L.supermap.tiledMapLayer(baseUrl, {noWrap: true}).addTo(map).on("load", function () {
findTSPPathsProcess();
});
//多旅行商分析服务
function findTSPPathsProcess() {
//添加站点
var myIcon = L.icon({
iconUrl: "https://iserver.supermap.io/iserver/iClient/forJavaScript/theme/images/marker.png",
iconSize: [44, 30]
});
var marker4 = L.marker([-1000, 3000], {icon: myIcon}).addTo(map);
var marker5 = L.marker([-4850, 3760], {icon: myIcon}).addTo(map);
var marker6 = L.marker([-2700, 8000], {icon: myIcon}).addTo(map);
//为配送点添加弹窗
marker4.bindPopup("零售站一");
marker5.bindPopup("零售站二");
marker6.bindPopup("零售站三");
//创建多旅行商分析服务实例
var serviceUrl = "https://iserver.supermap.io/iserver/services/transportationanalyst-sample/rest/networkanalyst/RoadNet@Changchun";
var findTSPPathsService = L.supermap.networkAnalystService(serviceUrl);
//向服务端发送请求,并返回结果进行处理
findTSPPathsService.findTSPPaths(findTSPPathsParams, function (serviceResult) {
var result = serviceResult.result;
result.tspPathList.map(function (result) {
L.geoJSON(result.route).addTo(map);
});
});
}
运行效果

示例:最近设施查找分析
最近设施分析是指在网络上给定一个事件点和一组设施点,为事件点查找以最小耗费能到达的一个或几个设施点,结果显示从事件点到设施点(或从设施点到事件点)的最佳路径,耗费,及行驶方向。例如事件发生点是一起交通事故,要求查找在10分钟内能到达的最近医院,超过10分钟能到达的都不予考虑。此例中,事故发生地即是一个事件点,周边的医院则是设施点。最近设施查找实际上也是一种路径分析,因此,同样可以应用障碍边和障碍点的设置,在行驶路途上这些障碍将不能被穿越,在路径分析中会予以考虑。
下面以长春数据为例,在地图上标记事故事件点,然后针对三个医院进行最近设施查找分析,其接口使用方法如下所示:
设置最近设施分析参数,包括交通网络分析通用参数、事件点、设施点、查找半径等。
//交通网络分析结果参数
var resultSetting = new SuperMap.TransportationAnalystResultSetting({
returnEdgeFeatures: true,//是否在分析结果中包含弧段要素集合
returnEdgeGeometry: true,//返回的弧段要素集合中是否包含集合对象信息
returnEdgeIDs: true,//返回的结果中是否包含经过弧段ID集合
returnNodeFeatures: true,//返回的分析结果总是否包含结点要素集合
returnNodeGeometry: true,//返回的结点要素集合中是否包含集合对象信息
returnNodeIDs: true,//返回的分析结果中是否包含经过结点ID集合
returnPathGuides: true,//返回分析结果中是否包含行驶导引集合
returnRoutes: true//返回结果中是否包含路由对象集合
};
//交通网络分析通用参数
var analystParameter = new SuperMap.TransportationAnalystParameter({
resultSetting: resultSetting,//分析结果返回内容
turnWeightField: "TurnCost",//转向权重字段的名称
weightFieldName: "length" //阻力字段的名称
});
//最近设施分析参数
var findClosetFacilitiesParams = new SuperMap.FindClosestFacilitiesParameters({
//事件点,一般为需要获得服务设施服务的事件位置
event: L.latLng(-3700, 5000),
//要查找的设施点数量
expectFacilityCount: 1,
//设施点集合,一般为提供服务的服务设施位置
facilities: [L.latLng(-3500, 2500), L.latLng(-2500, 5500), L.latLng(-4000, 7000)],
//事件点和设施点是否通过节点ID号来指定
isAnalyzeById: false,
//交通网络分析通用参数
parameter: analystParameter
});
定义最近设施查找分析对象,用于将客户端设置的最近设施查找分析服务参数传递给服务端, 并接收服务端返回的最近设施分析结果。当向服务端发送请求并且服务端成功返回结果时,用户可对获得的最近设施分析结果做相应处理。
//初始化地图,并为地图设置事件
var baseUrl = "https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/长春市区图";
var map = L.map('map', {
crs: L.CRS.NonEarthCRS({
bounds: L.bounds([48.4, -7668.25], [8958.85, -55.58]),
origin: L.point(48.4, -55.58)
}),
center: [-3600, 4700],
maxZoom: 18,
zoom: 2
});
L.supermap.tiledMapLayer(baseUrl, {noWrap: true}).addTo(map).on('load', function () {
findClosetFacilitiesProcess();
});
//设置最近设置查找分析服务
function findClosetFacilitiesProcess(){
//添加设施点
var marker1 = L.marker([-3500, 2500]).addTo(map);
marker1.bindPopup("设施点一");
var marker2 = L.marker([-2500, 5500]).addTo(map);
marker2.bindPopup("设施点二");
var marker3 = L.marker([-4000, 7000]).addTo(map);
marker3.bindPopup("设施点三");
//添加事件点
var myIcon = L.icon({
iconUrl: "https://iserver.supermap.io/iserver/iClient/forJavaScript/theme/images/marker.png",
iconSize: [44, 30]
});
var marker4 = L.marker([-3700, 5000], {icon: myIcon}).addTo(map);
marker4.bindPopup("事件点");
//创建最近设施分析服务实例
var serviceUrl = "https://iserver.supermap.io/iserver/services/transportationanalyst-sample/rest/networkanalyst/RoadNet@Changchun";
var findClosetFacilitiesService = L.supermap.networkAnalystService(serviceUrl);
//向服务端发送请求,并返回结果进行处理
findClosetFacilitiesService.findClosestFacilities(findClosetFacilitiesParams, function (serviceResult) {
var rersult = serviceResult.result;
rersult.facilityPathList.map(function (result) {
resultLayer = L.geoJSON(result.route).addTo(map);
});
});
}
运行效果

示例:选址分区分析
选址分区分析是为了确定一个或多个待建设施的最佳或最优位置,使得设施可以用一种最经济有效的方式为需求方提供服务或者商品。选址分区不仅仅是一个选址过程,还要将需求点的需求分配到相应的新建设施的服务区中,因此称之为选址与分区。
设置选址分区分析参数,包括交通网络分析通用参数、途径站点等
//选址分区中资源中心的类型,包括固定中心和可选中心两种
var supplyCenterType_FIXEDCENTER = SuperMap.SupplyCenterType.FIXEDCENTER,
var supplyCenterType_NULL = SuperMap.SupplyCenterType.NULL,
var supplyCenterType_OPTIONALCENTER = SuperMap.SupplyCenterType.OPTIONALCENTER;
var supplyCenters=[new SuperMap.REST.SupplyCenter({
maxWeight: 500,//资源供给中心最大耗费值
nodeID: 139,//资源供给中心点的结点ID
resourceValue: 100,//资源供给中心能提供的最大服务量或者商品数量
type: supplyCenterType_OPTIONALCENTER//选址分区中资源中心的类型
}),
new SuperMap.SupplyCenter({
maxWeight: 500,
nodeID: 1358,
resourceValue: 100,
type: supplyCenterType_OPTIONALCENTER
}),
new SuperMap.SupplyCenter({
maxWeight: 500,
nodeID: 2972,
resourceValue: 100,
type: supplyCenterType_OPTIONALCENTER
}),
new SuperMap.SupplyCenter({
maxWeight: 500,
nodeID: 5523,
resourceValue: 100,
type: supplyCenterType_OPTIONALCENTER
}),
new SuperMap.SupplyCenter({
maxWeight: 500,
nodeID: 1161,
resourceValue: 100,
type: supplyCenterType_OPTIONALCENTER
}),
new SuperMap.SupplyCenter({
maxWeight: 500,
nodeID: 4337,
resourceValue: 100,
type: supplyCenterType_OPTIONALCENTER
}),
new SuperMap.SupplyCenter({
maxWeight: 500,
nodeID: 5732,
resourceValue: 100,
type: supplyCenterType_NULL
}),
new SuperMap.SupplyCenter({
maxWeight: 500,
nodeID: 663,
resourceValue: 100,
type: supplyCenterType_FIXEDCENTER
})
];
//创建选址分区分析参数实例
var findLocationParams = new SuperMap.FindLocationParameters({
expectedSupplyCenterCount: 8, //期望用于最终设施选址的资源供给中心数量
isFromCenter: false, //是否从中心点开始分配资源
nodeDemandField: "Demand", //结点需求量字段
turnWeightField: "TurnCost", //转向权值字段的名称
weightName: "length", //阻力字段的名称
supplyCenters: supplyCenters //资源供给中心集合,必设字段
});
定义选址分区分析服务对象,用于将客户端设置的选址分区分析服务参数传递给服务端,并接收服务端返回的动态分段分析结果数据。当向服务端发送请求并且服务端成功返回结果时,用户可对获得的选址分区分析结果做相应处理。
//初始化地图,并为地图设置事件
var baseUrl = "https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/长春市区图";
var map = L.map('map', {
crs: L.CRS.NonEarthCRS({
bounds: L.bounds([48.4, -7668.25], [8958.85, -55.58]),
origin: L.point(48.4, -55.58)
}),
center: [-3600, 4700],
maxZoom: 18,
zoom: 2
});
L.supermap.tiledMapLayer(baseUrl, {noWrap: true}).addTo(map).on("load", function () {
findLocationProcess();
});
//选址分区服务结果处理
function findLocationProcess() {
//添加设施点
L.marker([-593.56822512495194, 1675.9256791377206]).addTo(map);
L.marker([-2358.0414663985171, 2820.35101097629]).addTo(map);
L.marker([-3647.0074300836109, 2909.4396668115278]).addTo(map);
L.marker([-5616.5950974905827, 1544.5037476378677]).addTo(map);
L.marker([-2130.4887600981415, 6623.5972101719526]).addTo(map);
L.marker([-4504.2328567816048, 5482.4979617984973]).addTo(map);
L.marker([-1627.6012900626256, 6940.6579024271468]).addTo(map);
L.marker([-5747.5063918659716, 8215.9188781715948]).addTo(map);
//创建选址分区分析服务实例
var serviceUrl = "https://iserver.supermap.io/iserver/services/transportationanalyst-sample/rest/networkanalyst/RoadNet@Changchun";
var findLocationService = L.supermap.networkAnalystService(serviceUrl);
//向服务端发送请求,并对返回结果进行处理
findLocationService.findLocation(findLocationParams, function (serviceResult) {
L.geoJSON(serviceResult.result.demandResults, {
pointToLayer: function (geoJsonPoint, latlng) {
return L.circleMarker(latlng, {radius: 1, color: "green"});
}
}).addTo(map);
});
}
运行效果

示例:多旅行商分析
多旅行商分析也称为物流配送,是指在网络数据集中,给定M个配送中心点和N个配送目的地(M,N为大于零的整数),查找经济有效的配送路径,并给出相应的行走路线。 多旅行商分析功能就是解决如何合理分配配送次序和送货路线,使配送总花费达到最小或每个配送中心的花费达到最小。
多旅行商分析的结果将给出,每个配送中心所负责的配送目的地,并且在某个配送中心向其负责的配送目的地配送货物的时候,又给出经过各个配送目的地的顺序,和相应的行走路线,从而使该配送中心的配送花费最少,或者使得所有的配送中心的总花费最小。
下面以长春数据为例,利用多旅行商分析和旅行商分析对食品厂各个仓库配送中心到用户指定的零售站的配送路线进行分析,并且给出质检员定期到各个零售站检查货品情况时所走的花费最小的路线,其接口使用方法如下所示:
设置多旅行商分析参数findMTSPPathsParams,包括交通网络分析通用参数、配送中心点集合、配送目标点集合、配送模式等
//交通网络分析结果参数
var resultSetting = new SuperMap.TransportationAnalystResultSetting({
returnEdgeFeatures: true,//是否在分析结果中包含弧段要素集合
returnEdgeGeometry: true,//返回的弧段要素集合中是否包含集合对象信息
returnEdgeIDs: true,//返回的结果中是否包含经过弧段ID集合
returnNodeFeatures: true,//返回的分析结果总是否包含结点要素集合
returnNodeGeometry: true,//返回的结点要素集合中是否包含集合对象信息
returnNodeIDs: true,//返回的分析结果中是否包含经过结点ID集合
returnPathGuides: true,//返回分析结果中是否包含行驶导引集合
returnRoutes: true//返回结果中是否包含路由对象集合
};
//交通网络分析通用参数
var analystParameter = new SuperMap.TransportationAnalystParameter({
resultSetting: resultSetting,//分析结果返回的内容
weightFieldName: "length"//阻力字段的名称
});
//多旅行商分析参数
var findMTSPPathsParams = new SuperMap.FindMTSPPathsParameters({
//配送中心集合
centers: [L.latLng(-5500, 6000), L.latLng(-2500, 5500), L.latLng(-3500, 2500)],
//是否通过节点ID号来指定配送中心点和配送目的点
isAnalyzeById: false,
//配送目标集合
nodes: [L.latLng(-5000, 5000), L.latLng(-2800, 8000)],
//配送模式是否为总花费最小方案
hasLeastTotalCost: true,
//交通网络分析通用参数
parameter: analystParameter
});
通过向服务端提交物流配送分析的请求参数,待服务端成功处理并返回分析处理结果后对其进行解析,获得由配送中心依次向各个配送目的地配送货物的最佳路径。
//初始化地图,并为地图设置事件
var baseUrl = "https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/长春市区图";
var map = L.map('map', {
crs: L.CRS.NonEarthCRS({
bounds: L.bounds([48.4, -7668.25], [8958.85, -55.58]),
origin: L.point(48.4, -55.58)
}),
center: [-3600, 4700],
maxZoom: 18,
zoom: 2
});
L.supermap.tiledMapLayer(baseUrl, {noWrap: true}).addTo(map).on("load", function () {
findMTSPPathsProcess();
});
//多旅行商分析结果处理
function findMTSPPathsProcess() {
//添加配送点
var marker1 = L.marker([-5500, 6000]).addTo(map);
var marker2 = L.marker([-2500, 5500]).addTo(map);
var marker3 = L.marker([-3500, 2500]).addTo(map);
//为配送点添加弹窗
marker1.bindPopup("配送中心点一");
marker2.bindPopup("配送中心点二");
marker3.bindPopup("配送中心点三");
//添加配送目的地
var myIcon = L.icon({
iconUrl: 'https://iserver.supermap.io/iserver/iClient/forJavaScript/theme/images/marker.png',
iconSize: [44, 30]
});
var marker4 = L.marker([-5000, 5000], {icon: myIcon}).addTo(map);
var marker5 = L.marker([-2800, 8000], {icon: myIcon}).addTo(map);
//为配送点添加弹窗
marker4.bindPopup("配送目的地一");
marker5.bindPopup("配送目的地二");
//创建多旅行商分析服务实例
var serviceUrl = "https://iserver.supermap.io/iserver/services/transportationanalyst-sample/rest/networkanalyst/RoadNet@Changchun";
var findMTSPPathsService = L.supermap.networkAnalystService(serviceUrl);
//向服务器发送请求,并对返回结果进行处理
findMTSPPathsService.findMTSPPaths(findMTSPPathsParams, function (serviceResult) {
var result = serviceResult.result;
result.pathList.map(function (result) {
L.geoJSON(result.route, {color: "green"}).addTo(map);
});
});
}
运行效果

使用交通换乘分析服务
交通换乘分析的使用方法如下:
- 定义起始站点和终点站点名查询函数;
- 进行交通换乘查询,首先需在客户端设置用于向服务端发送的交通换乘参数,其次定义交通换乘服务,用于向服务端发送请求并从服务端获得交通换乘结果数据,最后将返回的结果在客户端进行展示。
下面以长春交通数据模拟的公交线路数据为例,起点为省汽修,终点为中央大厦,范例提供了最少时间的换乘策略,用户可根据自己的需要选择最为合适的出行路线。
1. 交通换乘方案查询
交通方案查询:该方法返回所有的乘车方案,根据方案中的介绍信息可以获取具体的乘车路线。实现过程首先需要设置交通换乘参数,需要设置的参数包括solutionCount、transferTactic、transferPreference、walkingRatio、points,定义交通换乘服务函数,向服务端发送请求,待服务端成功处理并返回交通换乘结果数据。
var map, startMarker, endMarker, tempRedLayer, tempMarker,
routeFeatureGroup, paths = {transSolutions: null, solutions: null}, info,
baseUrl = "https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/长春市区图",
serviceUrl = "https://iserver.supermap.io/iserver/services/traffictransferanalyst-sample/restjsr/traffictransferanalyst/Traffic-Changchun";
//初始化地图
map = L.map('map', {
crs: L.CRS.NonEarthCRS({
bounds: L.bounds([48.4, -7668.25], [8958.85, -55.58]),
origin: L.point(48.4, -55.58)
}),
center: [-3900, 4700],
maxZoom: 18,
zoom: 2
});
L.supermap.tiledMapLayer(baseUrl, {noWrap: true}).addTo(map);
//设置起点
startMarker = L.marker([-5527.73795456, 3111.42533851]).addTo(map)
.bindTooltip("起点", {
offset: L.point([0, -10]),
direction: "top",
permanent: true
}).openTooltip();
//设置终点
endMarker = L.marker([-4270.0725196, 6055.3431955]).addTo(map)
.bindTooltip("终点", {
offset: L.point([0, -10]),
direction: "top",
permanent: true
}).openTooltip();
routeFeatureGroup = L.featureGroup().addTo(map); //建立临时站点图层
tempRedLayer = L.featureGroup().addTo(map); //建立临时交通线路图层
initResultInfoWin(); //初始化信息框
execTransSolutionsQuery('LESS_TIME'); //最少时间换乘查询
//初始化信息框
function initResultInfoWin() {
info = L.control({position: 'topright'}); //信息框显示在右上角
info.onAdd = function () {
this._div = L.DomUtil.create('div', 'panel panel-primary');
info.update();
handleMapEvent(this._div, this._map);
return this._div;
};
//地图事件
function handleMapEvent(div, map) {
if (!div || !map) {
return;
}
div.addEventListener('mouseover', function () {
map.dragging.disable();
map.scrollWheelZoom.disable();
map.doubleClickZoom.disable();
});
div.addEventListener('mouseout', function () {
map.dragging.enable();
map.scrollWheelZoom.enable();
map.doubleClickZoom.enable();
});
}
//信息框内容更新
info.update = function (transSolutions, transGuide) {
if (!transSolutions) {
return;
}
var solution, lines, line, dispStatus = "block";
$("<div class='panel-heading' style='background:steelblue;color: honeydew'>起点:省汽修 终点:中安大厦<br/>乘车方案(最少时间)</div>").appendTo(this._div);
for (var i = 0, iLen = transSolutions.length; i < iLen; i++) {
solution = transSolutions[i];
//显示方案头
var title = "";
for (var ii = 0, iiLen = solution.linesItems.length; ii < iiLen; ii++) {
lines = solution.linesItems[ii];
for (var iii = 0, iiiLen = lines.lineItems.length; iii < iiiLen; iii++) {
line = lines.lineItems[iii];
if (iii !== iiiLen - 1) {
title += line.lineName + "/";
} else {
title += line.lineName;
}
}
if (ii !== iiLen - 1) {
title += " → ";
}
}
$("<div class='transferSolution' id='transferSolution-" + i + "'><span class='transferIndex'>方案" + (i + 1) + ":</span>" + title + "</div>").appendTo(this._div);
if (i !== 0) {
dispStatus = "none";
}
var list = $("<div class='transferInfo' id='transferInfo-" + i + "' style='display:" + dispStatus + "'></div>");
list.appendTo(this._div);
//默认显示方案1下的table
if (i === 0) {
fillTransferInfo(transGuide, transSolutions, 0).appendTo(list);
setPopup();
}
}
//点击方案时显示对应的table
bindSolutionsClickEvent();
};
info.addTo(map);
}
//显示方案indexX下的table
function fillTransferInfo(transGuide, transSolutions, indexX) {
clearLayer();
if (transGuide && transGuide.items.length) {
var items = transGuide.items;
for (var itemIndex = 0, itemLen = items.length; itemIndex < itemLen; itemIndex++) {
var geometry = items[itemIndex].route;
routeFeatureGroup.addLayer(L.geoJSON(L.Util.toGeoJSON(geometry)).addTo(map));
}
}
var table = $("<table id='trafficRes' border='1'></table>");
var startStop = $("<tr></tr>");
$("<td class='start_transfer' width='10px'></td>").appendTo(startStop);
$("<td colspan='2'><span class='busLink bgSpan'><span style='display:none'>" + transGuide.items[0].startPosition.x + "," + transGuide.items[0].startPosition.y + "</span>" + transGuide.items[0].startStopName + "</span></td>").appendTo(startStop);
startStop.appendTo(table);
var indexY = 0;
for (var iiii = 0, iiiiLen = transGuide.items.length; iiii < iiiiLen; iiii++) {
var item = transGuide.items[iiii];
var tr2 = $("<tr></tr>");
if (item.isWalking) {
$("<td class='step_transfer' ></td>").appendTo(tr2);
$("<td>步行至:<a class='busLink'><span style='display:none'>" + item.endPosition.x + "," + item.endPosition.y + "</span>" + item.endStopName + "</a></td>").appendTo(tr2);
$("<td>" + parseInt(item.distance) + "米</td>").appendTo(tr2);
} else {
var otherLines = transSolutions[indexX].linesItems[indexY],
links = "";
if (otherLines && otherLines.lineItems.length > 1) {
links = "</br>还可乘坐:"
for (var oti = 0, otLen = otherLines.lineItems.length; oti < otLen; oti++) {
var line = otherLines.lineItems[oti];
if (item.lineName !== line.lineName) {
var other = indexX + "," + indexY + "," + oti + ",0";
links += "<a class='busLink'><span style='display:none'>" + other + "</span>" + line.lineName + "</a>";
}
}
}
$("<td class='bus_transfer'></td>").appendTo(tr2);
var points = item.route.points, pointStr = "";
for (var i = 0; i < points.length; i++) {
pointStr += points[i].x + " " + points[i].y;
if (i != points.length - 1) {
pointStr += ",";
}
}
$("<td>乘坐<a class='busLink'>" + item.lineName + "<span style='display:none'>" + pointStr + "</span></a>, 在<a class='busLink'><span style='display:none'>" + item.endPosition.x + "," + item.endPosition.y + "</span>" + item.endStopName + "</a>下车" + links + "</td>").appendTo(tr2);
$("<td>" + item.passStopCount + "站</td>").appendTo(tr2);
indexY++;
}
tr2.appendTo(table);
}
var endStop = $("<tr></tr>");
endStop.appendTo(table);
$("<td class='end_transfer' width='10px'></td>").appendTo(endStop);
$("<td colspan='2'><span class='busLink bgSpan'><span style='display:none'>" + transGuide.items[transGuide.items.length - 1].endPosition.x + "," + transGuide.items[transGuide.items.length - 1].endPosition.y + "</span>" + transGuide.items[transGuide.items.length - 1].endStopName + "</span></td>").appendTo(endStop);
return table;
}
// 定义公交换乘方案查询
function execTransSolutionsQuery(tactic) {
//清除上一次方案的结果
info.remove();
paths.points = [26, 180];
//配置公交换乘方案查询参数
var params = new SuperMap.TransferSolutionParameters({
solutionCount: 6,//最大换乘导引数量
transferTactic: tactic,//公交换乘策略类型
walkingRatio: 10,//步行与公交的消耗权重比
points: paths.points //起始点坐标
});
var serviceUrl = "https://iserver.supermap.io/iserver/services/traffictransferanalyst-sample/restjsr/traffictransferanalyst/Traffic-Changchun";
//向服务器发送请求,并对返回的结果进行处理
L.supermap.trafficTransferAnalystService(serviceUrl)
.analysisTransferSolution(params, function (serviceResult) {
if (serviceResult.error) {
alert("错误提示:" + serviceResult.error.errorMsg);
}
transferSolutionsSucceed(serviceResult.result);
});
}
//执行公交换乘方案成功返回结果
function transferSolutionsSucceed(result) {
clearLayer();
info.addTo(map);
//在地图上叠加符号信息
//transGuide: 交通换乘导引记录了从换乘分析起始站点到终止站点的交通换乘导引方案。
//交通换乘导引由交通换乘导引子项(TransferGuideItem类型对象)构成,
//每一个导引子项可以表示一段换乘或者步行线路。 通过本类型可以返回交通换乘导引对象中
//子项的个数,根据序返回交通换乘导引的子项对象,导引总距离以及总花费等
//transSolutions: 交通换乘方案类。在一个换乘方案内的所有乘车路线中换乘次数是相同的
var transGuide = result.defaultGuide,
transSolutions = result.solutionItems,
solutions = [];
for (var j = 0; j < transSolutions.length; j++) {
var linesItems = transSolutions[j].linesItems, transSolution = [];
for (var jj = 0; jj < linesItems.length; jj++) {
var lineItems = linesItems[jj].lineItems, items = [];
for (var jjj = 0; jjj < lineItems.length; jjj++) {
var lineItem = lineItems[jjj];
items.push("{'lineID':" + lineItem.lineID +
",'startStopIndex':" + lineItem.startStopIndex +
",'endStopIndex':" + lineItem.endStopIndex + "}"
);
}
transSolution.push(items);
}
solutions.push(transSolution);
}
paths["transSolutions"] = transSolutions;
paths["solutions"] = solutions;
if (!transGuide || !transSolutions) return;
info.update(transSolutions, transGuide);
}
//清除所有结果图层
function clearLayer() {
if (routeFeatureGroup) {
routeFeatureGroup.clearLayers();
}
if (tempRedLayer) {
tempRedLayer.clearLayers();
}
if (tempMarker) {
tempMarker.remove();
}
}
2. 乘车路线查询
根据换乘方案查询结果(transferSolutions)得到的乘车方案,获取某一条乘车路线的详细信息。
//点击某一方案时获取具体的路线
function bindSolutionsClickEvent() {
for (var i = 0; i < 6; i++) {
$("#transferSolution-" + i).click(toggleGuideItems);
}
function toggleGuideItems(e) {
for (var j = 0; j < 6; j++) {
$("#transferInfo-" + j).hide(500);
}
var id = parseInt(e.currentTarget.id.split("-")[1]);
$("#transferInfo-" + id).show(500);
//构造传入iServer服务器的transferLines
var transLines = [];
for (var i = 0; i < paths.solutions[id].length; i++) {
var trans = paths.solutions[id][i][0];
transLines.push(trans);
}
execTransPathQuery(id, transLines);
}
}
//获取乘车路线的详细信息
function execTransPathQuery(id, transLines) {
//设置乘车线路参数
var params = new SuperMap.TransferPathParameters({
points: paths["points"], //起始点坐标
transferLines: transLines //当前换乘路线,包含路线ID、起止点等
});
//向服务器发送请求,并对返回的结果进行处理
L.supermap.trafficTransferAnalystService(serviceUrl)
.analysisTransferPath(params, function (serviceResult) {
$("#transferInfo-" + id).empty();
var transGuide = serviceResult.result;
transSolutions = paths["transSolutions"];
map.setView([-3900, 4700], 2);
fillTransferInfo(transGuide, transSolutions, id)
.appendTo($("#transferInfo-" + id));
setPopup();
});
}
//在地图上显示查询出的临时站点和路线
function setPopup() {
$(".busLink").click(function () {
tempRedLayer.clearLayers(); //清除临时路线图层
if (tempMarker) tempMarker.remove(); //清除临时站点图层
var points = this.children[0].innerText.split(","), lonLat;
if (points.length === 2) {
lonLat = L.latLng(points[1], points[0]);
tempMarker = L.marker(lonLat).addTo(map);
map.setView(lonLat);
} else if (points.length === 4 && points[3] === "0") {
var linesItems = paths["solutions"][points[0]], lineStr = "[";
for (var i = 0; i < linesItems.length; i++) {
var lineItem = linesItems[i][0], j = parseInt(points[1]);
if (i !== j) {
lineStr += lineItem;
} else if (i === j) {
lineItem = linesItems[points[1]][points[2]];
lineStr += lineItem;
}
if (i !== linesItems.length - 1) {
lineStr += ",";
}
}
lineStr += "]";
$("#transferInfo-" + points[0]).hide(500);
execTransPathQuery(points[0], lineStr);
$("#transferInfo-" + points[0]).show(500);
} else {
var linePoints = [];
for (var i = 0; i < points.length; i++) {
var arr = points[i].split(" ");
var point = [arr[1], arr[0]];
linePoints.push(point);
}
var lineString = L.polyline(linePoints, {color: "red"}).addTo(map);
tempRedLayer.addLayer(lineString);
map.setView(lineString.getBounds().getCenter(), 3);
}
});
}
运行效果
这里仅展示最少时间查询结果,其中起始站点为省汽修,终点站点为中安大厦,查询效果图如下所示:

使用分布式分析服务
SuperMap iClient for Leaflet支持的分布式分析服务包含:
- 密度分析
- 点聚合分析
- 单对象查询分析
- 区域汇总分析
- 矢量剪裁分析
示例:密度分析
分布式分析服务中的密度分析包括简单点密度分析和核密度分析两种
- 简单点密度分析:用于计算每个点的指定邻域形状内的每单位面积量值。计算方法为点的测量值除以指定邻域面积,点的邻域叠加处,其密度值也相加,每个输出栅格的密度均为叠加在栅格上的所有邻域密度值之和。结果栅格值的单位为原数据集单位的平方的倒数,即若原数据集单位为米,则结果栅格值的单位为每平方米。
- 核密度分析:用于计算点、线要素测量值在指定邻域范围内的单位密度。简单来说,它能直观的反映出离散测量值在连续区域内的分布情况。其结果是中间值大周边值小的光滑曲面,栅格值即为单位密度,在邻域边界处降为0。核密度分析可用于计算人口密度、建筑密度、获取犯罪情况报告、旅游区人口密度监测、连锁店经营情况分析等等。
下面对已注册的大数据进行简单点密度分析,网格面类型为四边形网格。其接口使用方法如下:
设置密度分析参数kernelDensityJobParams,包括数据集、分析方法、分析类型、格网大小等。
//密度分析参数
var kernelDensityJobParams = new SuperMap.KernelDensityJobParameter({
//已注册的数据集名
datasetName: "newyork_taxi_2013_01_14k_csv_newyork_taxi_2013-01_14k",
//网格大小,对于四边形网格为网格的边长;对于六边形网格为六边形顶点到中心点的距离
resolution: 80,
//分析方法, 指定分析方法为简单点密度分析,还是核密度分析。0表示前者,1表示后者
method:0,
//格网面类型, 指定网格单元为四边形网格,还是六边形网格。0表示前者,1表示后者
meshType:0,
//指定待分析的点的权重值所在的字段索引列号集合,字段索引从0开始。格式如:col7,col8
fields: col7,col8,
query: Bounds, //分析范围
radius: 300, //分析的影响半径
meshSizeUnit: Meter, //网格大小单位
radiusUnit: Meter, //搜索半径单位
areaUnit: SquareMile, //面积单位
});
向服务端提交密度分析的请求,待服务端成功处理并返回密度分析结果后对其进行解析处理,将其在地图中展现出来。
//初始化地图
var map = L.map('map', {
crs: L.CRS.TianDiTu_WGS84,
center: [40.75, -73.95],
maxZoom: 18,
zoom: 12
}),
//在地图上添加天地图图层
L.supermap.tiandituTileLayer("http://t{s}.tianditu.com/vec_c/wmts", {
layer: "vec",
tilematrixSet: "c"
}).addTo(map);
//创建分布式分析服务
var processingUrl ="http://localhost:8090/iserver/services/spatialprocessing/rest/v1/jobs";
var processingService = new L.supermap.processingService(processingUrl);
//向服务器发送请求进行密度分析服务,并对返回结果进行处理展现在地图上
processingService.addKernelDensityJob(kernelDensityJobParams, function (serviceResult) {
//分析失败时弹窗警告框并显示错误信息
if (serviceResult.error) {
var errorMsg = serviceResult.error.errorMsg || "code: " + serviceResult.error.code;
showAlert("创建失败!
" + errorMsg, false);
return;
}
//分析成功时对结果进行处理展现在地图上
serviceResult.result.setting.serviceInfo.targetServiceInfos.map(function (info) {
if (info.serviceType === 'RESTMAP') {
SuperMap.FetchRequest.get(info.serviceAddress + '/maps')
.then(function(response) {return response.json();}).then(function (result) {
var mapUrl = result[0].path;
var layer = L.supermap.imageMapLayer(mapUrl, {noWrap: true, transparent: true});
layer.addTo(map);
});
}
});
});
运行效果

示例:点聚合分析
点聚合分析,指的是针对点数据集制作聚合图的一种空间分析作业。指通过网格面或多边形对地图点要素进行划分,然后,计算每个面对象内点要素的数量,并作为面对象的统计值,也可以引入点的权重信息,考虑面对象内点的加权值作为面对象的统计值;最后基于面对象的统计值,按照统计值大小排序的结果,通过色带对面对象进行色彩填充。
目前支持的点聚合分析类型包括:网格面聚合和多边形聚合,其中网格面聚合图按照网格类型又可分为四边形网格和六边形网格。
下面对已注册的大数据进行点聚合分析,其中聚合类型为网格面聚合,网格面类型为四边形网格。其接口使用方法如下:
设置点聚合分析参数summaryMeshJobParam,包括数据集、聚合类型、统计模式、格网大小等。
//点聚合分析参数
var summaryMeshJobParam = new SuperMap.SummaryMeshJobParameter({
//已注册的数据集名
datasetName: "newyork_taxi_2013_01_14k_csv_newyork_taxi_2013-01_14k",
//网格大小,对于四边形网格为网格的边长;对于六边形网格为六边形顶点到中心点的距离
resolution: 80,
//网格面类型, 指定网格单元为四边形网格,还是六边形网格。0表示前者,1表示后者
meshType:0,
//指定待分析的点的权重值所在的字段索引列号集合,字段索引从0开始。格式如:col7,col8
fields: col7,
query: Bounds, //分析范围
statisticModes:,//统计模式, 需与“权重值字段”个数保持一致
type:, SummaryType//聚合类型, 指定聚合类型为网格面聚合,还是多边形聚合。
//regionDataset: 'regionDataset', 聚合面数据集, 在多边形聚合时使用
});
向服务端提交点聚合分析的请求,待服务端成功处理并返回点聚合分析结果后对其进行解析处理,将其在地图中展现出来。
//初始化地图
var map = L.map('map', {
crs: L.CRS.TianDiTu_WGS84,
center: [40.75, -73.95],
maxZoom: 18,
zoom: 12
}),
//在地图上添加天地图图层
L.supermap.tiandituTileLayer("http://t{s}.tianditu.com/vec_c/wmts", {
layer: "vec",
tilematrixSet: "c"
}).addTo(map);
//创建分布式分析服务
var processingUrl ="http://localhost:8090/iserver/services/spatialprocessing/rest/v1/jobs";
var processingService = new L.supermap.processingService(processingUrl);
//向服务器发送请求进行点聚合分析服务,并对返回结果进行处理展现在地图上
processingService.addSummaryMeshJob(summaryMeshJobParam,function(serviceResult){
//分析失败时弹窗警告框并显示错误信息
if (serviceResult.error) {
var errorMsg = serviceResult.error.errorMsg || "code: " + serviceResult.error.code;
showAlert("创建失败!
" + errorMsg, false);
return;
}
//分析成功时对结果进行处理展现在地图上
serviceResult.result.setting.serviceInfo.targetServiceInfos.map(function (info) {
if (info.serviceType === 'RESTMAP') {
SuperMap.FetchRequest.get(info.serviceAddress + '/maps')
.then(function(response) {return response.json();}).then(function (result) {
var mapUrl = result[0].path;
var layer = L.supermap.imageMapLayer(mapUrl, {noWrap: true, transparent: true});
layer.addTo(map);
});
}
});
});
运行效果

示例:单对象查询分析
空间查询是通过几何对象之间的空间位置关系来构建过滤条件的一种查询方式。例如:通过空间查询可以找到被包含在面中的空间对象,相离或者相邻的空间对象等。
分布式分析服务中的单对象空间查询,指的是只支持查询对象数据集中有一个对象对被查询数据集做空间查询。如果查询对象数据集中有多个对象,则默认用 SmID 最小的对象对被查询数据集做空间查询。
下面对已注册的大数据进行单对象查询分析,其中空间查询模式使用“相交”。其接口使用方法如下:
设置单对象查询分析参数singleObjectQueryJobsParam,包括源数据集、查询对象数据集、空间查询模式。
//单对象查询分析参数
var singleObjectQueryJobsParam = new SuperMap.SingleObjectQueryJobsParameter({
datasetName: 'ProcessingData_processing_newyorkZone_R', //已注册的数据集名
datasetQuery: 'ProcessingData_processing_singleRegion_R', //查询对象所在数据集名称
mode:SpatialQueryMode //空间查询模式
});
向服务端提交单对象查询分析的请求,待服务端成功处理并返回单对象查询分析结果后对其进行解析处理,将其在地图中展现出来。
//初始化地图
var map = L.map('map', {
crs: L.CRS.TianDiTu_WGS84,
center: [40.75, -73.95],
maxZoom: 18,
zoom: 12
}),
//在地图上添加天地图图层
L.supermap.tiandituTileLayer("http://t{s}.tianditu.com/vec_c/wmts", {
layer: "vec",
tilematrixSet: "c"
}).addTo(map);
//创建分布式分析服务
var processingUrl ="http://localhost:8090/iserver/services/spatialprocessing/rest/v1/jobs";
var processingService = new L.supermap.processingService(processingUrl);
//向服务器发送请求进行单对象查询分析服务,并对返回结果进行处理展现在地图上
processingService.addQueryJob(singleObjectQueryJobsParam,function(serviceResult){
//分析失败时弹窗警告框并显示错误信息
if (serviceResult.error) {
var errorMsg = serviceResult.error.errorMsg || "code: " + serviceResult.error.code;
showAlert("创建失败!
" + errorMsg, false);
return;
}
//分析成功时对结果进行处理展现在地图上
serviceResult.result.setting.serviceInfo.targetServiceInfos.map(function (info) {
if (info.serviceType === 'RESTMAP') {
SuperMap.FetchRequest.get(info.serviceAddress + '/maps')
.then(function(response) {return response.json();}).then(function (result) {
var mapUrl = result[0].path;
var layer = L.supermap.imageMapLayer(mapUrl, {noWrap: true, transparent: true});
layer.addTo(map);
});
}
});
});
运行效果

示例:区域汇总分析
区域汇总分析,指的是针对线数据集和面数据集制作聚合图的一种空间分析作业。指通过网格面或多边形对地图线或面要素进行划分,然后,以标准属性字段或权重字段对每个网格单元内线或面要素进行统计,将统计结果作为该网格单元的统计值。最后按照网格单元统计值的大小进行排序,通过色带对网格单元进行色彩填充。
区域汇总分析的概念与点聚合分析的概念类似,不同的是点聚合分析是对点数据集进行统计计算,而区域汇总分析,是对线数据集和面数据集进行统计计算。在区域汇总分析的概念里,网格单元的统计值有两种统计方式,以标准属性字段统计和以权重字段统计。
下面对已注册的大数据进行区域汇总分析,其中汇总类型为网格面汇总,网格面类型为四边形网格。其接口使用方法如下:
设置区域汇总分析参数summaryRegionJobParam,包括数据集、汇总类型、网格面汇总类型等。
//区域汇总分析参数
var summaryRegionJobParam = new SuperMap.SummaryRegionJobParameter({
datasetName: 'ProcessingData_processing_newyorkZone_R', //已注册的数据集名
//regionDataset: 'regionDataset', 聚合面数据集, 在多边形聚合时使用
type: SummaryType, //汇总类型,包括网格面汇总和多边形汇总两种类型
//网格面类型, 指定网格单元为四边形网格,还是六边形网格。0表示前者,1表示后者
meshType:0,
query: Bounds, //分析范围
standardSummaryFields: true, //是否以标准属字段统计
//当以标准属字段统计时,标准属字段统计的统计模式
standardStatisticModes: StatisticAnalystMode,
standardFields: "LocationID", //当以标准属字段统计时,标准属字段统计的字段名称
weightedFields:false, //是否以权重字段统计
weightedStatisticModes: "", //使用权重字段统计模式,权重字段统计的统计模式
weightedSummaryFields: "",//使用权重字段统计模式时,权重字段统计的字段名称
//网格大小,对于四边形网格为网格的边长;对于六边形网格为六边形顶点到中心点的距离
resolution:100,
meshSizeUnit: Meter, //网格大小单位
sumShape:true //是否统计长度或面积
});
2. 向服务端提交区域汇总分析的请求,待服务端成功处理并返回区域汇总分析结果后对其进行解析处理,将其在地图中展现出来。
//初始化地图
var map = L.map('map', {
crs: L.CRS.TianDiTu_WGS84,
center: [40.75, -73.95],
maxZoom: 18,
zoom: 12
}),
//在地图上添加天地图图层
L.supermap.tiandituTileLayer("http://t{s}.tianditu.com/vec_c/wmts", {
layer: "vec",
tilematrixSet: "c"
}).addTo(map);
//创建分布式分析服务
var processingUrl ="http://localhost:8090/iserver/services/spatialprocessing/rest/v1/jobs";
var processingService = new L.supermap.processingService(processingUrl);
//向服务器发送请求进行区域汇总分析服务,并对返回结果进行处理展现在地图上
processingService.addSummaryRegionJob(summaryRegionJobParam,
function(serviceResult){
//分析失败时弹窗警告框并显示错误信息
if (serviceResult.error) {
var errorMsg = serviceResult.error.errorMsg || "code: " + serviceResult.error.code;
showAlert("创建失败!
" + errorMsg, false);
return;
}
//分析成功时对结果进行处理展现在地图上
serviceResult.result.setting.serviceInfo.targetServiceInfos.map(function (info) {
if (info.serviceType === 'RESTMAP') {
SuperMap.FetchRequest.get(info.serviceAddress + '/maps')
.then(function(response) {return response.json();}).then(function (result) {
var mapUrl = result[0].path;
var layer = L.supermap.imageMapLayer(mapUrl, {noWrap: true, transparent: true});
layer.addTo(map);
});
}
});
});
运行效果

示例:矢量裁剪分析
矢量裁剪分析为对矢量数据集进行裁剪。包括内部裁剪和外部裁剪。内部裁剪,则被裁剪的矢量数据集在裁剪区范围内的部分被保留到结果数据集中;相反,使用外部裁剪,则保留不在裁剪区范围内的那部分数据到结果数据集中。
分布式分析服务中的矢量裁剪分析,只支持裁剪对象数据集中有一个对象对源数据集做矢量裁剪。如果裁剪数据集中有多个对象,则默认用 SmID 最小的对象对源数据集做矢量裁剪。
下面对已注册的大数据进行矢量裁剪分析,裁剪矢量分析模式使用内部裁剪。其接口使用方法如下:
设置矢量裁剪分析参数vectorClipJobsParam,包括源数据、裁剪对象数据集、裁剪分析模式。
//矢量裁剪分析参数
var vectorClipJobsParam = new SuperMap.VectorClipJobsParameter({
datasetName: 'ProcessingData_newyork_taxi_2013-01_14k', //已注册的数据集名
datasetOverlay: 'ProcessingData_processing_singleRegion_R',//裁剪对象所在数据集名称
mode:ClipAnalystMode //裁剪分析模式
});
向服务端提交矢量裁剪分析的请求,待服务端成功处理并返回矢量裁剪分析结果后对其进行解析处理,将其在地图中展现出来。
//初始化地图
var map = L.map('map', {
crs: L.CRS.TianDiTu_WGS84,
center: [40.75, -73.95],
maxZoom: 18,
zoom: 12
}),
//在地图上添加天地图图层
L.supermap.tiandituTileLayer("http://t{s}.tianditu.com/vec_c/wmts", {
layer: "vec",
tilematrixSet: "c"
}).addTo(map);
//创建分布式分析服务
var processingUrl ="http://localhost:8090/iserver/services/spatialprocessing/rest/v1/jobs";
var processingService = new L.supermap.processingService(processingUrl);
//向服务器发送请求进行矢量裁剪分析服务,并对返回结果进行处理展现在地图上
processingService.addVectorClipJob(vectorClipJobsParam, function(serviceResult){
//分析失败时弹窗警告框并显示错误信息
if (serviceResult.error) {
var errorMsg = serviceResult.error.errorMsg || "code: " + serviceResult.error.code;
showAlert("创建失败!
" + errorMsg, false);
return;
}
//分析成功时对结果进行处理展现在地图上
serviceResult.result.setting.serviceInfo.targetServiceInfos.map(function (info) {
if (info.serviceType === 'RESTMAP') {
SuperMap.FetchRequest.get(info.serviceAddress + '/maps')
.then(function(response) {return response.json();}).then(function (result) {
var mapUrl = result[0].path;
var layer = L.supermap.imageMapLayer(mapUrl, {noWrap: true, transparent: true});
layer.addTo(map);
});
}
});
});
运行效果

使用数据流服务
//创建实时数据图层
var urlDataFlow = "ws://localhost:8091/iserver/services/dataflow/dataflow";
var dataFlowLayer = L.supermap.dataFlowLayer(urlDataFlow, {
//可选参数,GeoJSON要素过滤该范围内要素才会返回
geometry:{coordinates:[[[116.38,39.87],[116.41,39.87],[116.41,39.84],[116.38, 39.84],[116.38,39.87]]],type:"Polygon"},
//可选参数,返回要素不包括的字段值
excludeField:["id"],
//可选参数,返回要素坐标系
prjCoordSys:4326
});
dataFlowLayer.addTo(map);
下面的结果图为不同时刻实时数据的效果图,可以看到数据在不同时刻展现在地图不同的位置上。
运行效果


使用地址匹配服务
SuperMap iClient for Leaflet支持地址匹配服务。地址匹配服务包含正向匹配与反向匹配两种方式,即,用户可通过地点名称找到地址位置,也可以找到指定位置上的地点。
下面以China_4326数据为例,在其上进行地址匹配服务分析。
示例:正向地址匹配
正向地址匹配根据地点描述、城市范围返回对应的地理坐标和结构化的地址详细描述,支持中文模糊匹配。
//初始化地图
var baseUrl = 'https://iserver.supermap.io/iserver/services/map-china400/rest/maps/China_4326';
var map = L.map('map', {
crs: L.CRS.EPSG4326,
center: [39.914714, 116.383572],
maxZoom: 18,
zoom: 11
});
L.supermap.tiledMapLayer(baseUrl).addTo(map);
//正向匹配参数
var geoCodeParam = new SuperMap.GeoCodingParameter({
address: "超图软件", //地址
fromIndex:0, //最小索引
toIndex:10, //最大索引
filters: "公司", //过滤条件
prjCoordSys:{epsgcode26}, //坐标设置
maxReturn:3 //最大结果数
});
//创建地址匹配服务
var addressUrl = "https://iserver.supermap.io/iserver/services/addressmatch-Address/restjsr/v1/address",
var addressMatchService = L.supermap.addressMatchService(addressUrl);
//向服务端发送请求进行正向地址匹配,并对返回的结果进行处理
addressMatchService.code(geoCodeParam, match);
//对返回的结果进行处理展现在地图上,并添加弹窗
function match(obj) {
obj.result.map(function (item) {
var marker = L.marker([item.location.y, item.location.x]);
decodeMarkers.push(marker);
var innerHTML = "";
innerHTML += "地址:" + item.address + "<br>";
var x = Number(item.location.x.toString().match(/^\d+(?:\.\d{0,2})?/));
var y = Number(item.location.y.toString().match(/^\d+(?:\.\d{0,2})?/));
innerHTML += "坐标:[" + x + "," + y + "]<br>";
if (item.score > 0) {
innerHTML += "匹配度:" + item.score + "<br>";
}
innerHTML += "过滤字段:" + item.filters + "<br>";
marker.bindPopup(innerHTML);
});
for (var i = 0; i < decodeMarkers.length; i++) {
decodeMarkers[i].addTo(map);
}
map.setView(L.latLng(39.914714, 116.383572), 10);//设置地图显示范围
}
运行效果

示例:反向地址匹配
反向地址匹配根据输入的地址坐标获取对应的地址描述
//初始化地图
var baseUrl = 'https://iserver.supermap.io/iserver/services/map-china400/rest/maps/China_4326';
var map = L.map('map', {
crs: L.CRS.EPSG4326,
center: [39.914714, 116.383572],
maxZoom: 18,
zoom: 11
});
L.supermap.tiledMapLayer(baseUrl).addTo(map);
//反向匹配参数
var geoDecodeParam = new SuperMap.GeoDecodingParameter({
x:116.3518541194, //横坐标
y:40.00097839595, //纵坐标
fromIndex:0, //最小索引
toIndex:10, //最大索引
filters: "", //过滤字段
prjCoordSys:{epsgcode26}, //坐标设置
maxReturn:3, //最大结果数
geoDecodingRadius:1000 //查询半径
});
//创建地址匹配服务
var addressUrl = "https://iserver.supermap.io/iserver/services/addressmatch-Address/restjsr/v1/address",
var addressMatchService = L.supermap.addressMatchService(addressUrl);
//向服务端发送请求进行反向地址匹配,并对返回的结果进行处理
addressMatchService.decode(geoDecodeParam, match);
//对返回的结果进行处理展现在地图上,并添加弹窗
function match(obj) {
obj.result.map(function (item) {
var marker = L.marker([item.location.y, item.location.x]);
decodeMarkers.push(marker);
var innerHTML = "";
innerHTML += "地址:" + item.address + "<br>";
var x = Number(item.location.x.toString().match(/^\d+(?:\.\d{0,2})?/));
var y = Number(item.location.y.toString().match(/^\d+(?:\.\d{0,2})?/));
innerHTML += "坐标:[" + x + "," + y + "]<br>";
if (item.score > 0) {
innerHTML += "匹配度:" + item.score + "<br>";
}
innerHTML += "过滤字段:" + item.filters + "<br>";
marker.bindPopup(innerHTML);
});
for (var i = 0; i < decodeMarkers.length; i++) {
decodeMarkers[i].addTo(map);
}
map.setView(L.latLng(39.914714, 116.383572), 10);//设置地图显示范围
}
运行效果
