SuperMap iClient for Leaflet
Getting Started with Development
Here we use the World map service published by SuperMap iServer to introduce how to create a simple map application using SuperMap iClient for JavaScript.
Introduce leaflet.js or leaflet.min.js. For Leaflet, please introduce BootCDN host addresss:
<script type="text/javascript" src="https://cdn.bootcss.com/leaflet/1.0.3/leaflet.js"></script>
Introduce iclient9-leaflet.js or iclient9-leaflet.min.js:
<script type="text/javascript" src="https://iclient.supermap.io/dist/iclient9-leaflet.js"></script>
Load services published by iServer to map of Leaflet:
var map = L.map('map');
L.supermap.tiledMapLayer("http://localhost:8090/iserver/services/map/rest/maps/China").addTo(map);view source code »
Run Effects

npm
Install
npm install @supermap/iclient-leaflet
ES6 development Example
Example 1 (import partial modules)
import L from 'leaflet';
import {tiledMapLayer} from '@supermap/iclient-leaflet';
var url = "https://iserver.supermap.io/iserver/services/map-world/rest/maps/World";
var map = L.map('map', {
crs: L.CRS.EPSG4326,
center: [0, 0],
maxZoom: 18,
zoom: 1
});
tiledMapLayer(url).addTo(map);
Example 2 (import all modules)
import L from 'leaflet';
import '@supermap/iclient-leaflet';
var url = "https://iserver.supermap.io/iserver/services/map-world/rest/maps/World";
var map = L.map('map', {
crs: L.CRS.EPSG4326,
center: [0, 0],
maxZoom: 18,
zoom: 1
});
L.supermap.tiledMapLayer(url).addTo(map);
CommonJS development Example
Example 1 (import partial modules)
var L = require('leaflet');
var tiledMapLayer = require('@supermap/iclient-leaflet').tiledMapLayer;
var url = "https://iserver.supermap.io/iserver/services/map-world/rest/maps/World";
var map = L.map('map', {
crs: L.CRS.EPSG4326,
center: [0, 0],
maxZoom: 18,
zoom: 1
});
tiledMapLayer(url).addTo(map);
Example 2 (import all modules)
var L = require('leaflet');
require('@supermap/iclient-leaflet');
var url = "https://iserver.supermap.io/iserver/services/map-world/rest/maps/World";
var map = L.map('map', {
crs: L.CRS.EPSG4326,
center: [0, 0],
maxZoom: 18,
zoom: 1
});
L.supermap.tiledMapLayer(url).addTo(map);
About pacing
Because iClient uses ES6, in order to be compatible with browsers that do not support ES6, some configuration needs to be performed during the packaging process, including loading images and CSS files and processing the syntax conversion.
If you use webpack, you need to add the following configuration items in the webpack.config.js.
module: {
rules: [{
// Load image files, encoding images Which are less than 80k with base64.
test: /\.(png|jpg|jpeg|gif|woff|woff2|svg|eot|ttf)$/,
use: [{
loader: 'url-loader',
options: {
limit: 80000
}
}]
}, {
// Load CSS files
test: /\.css$/,
use: ['css-loader']
}, {
// Use the babel-loader to convert ES6 syntax to ES5.
test: /\.js$/,
include: [
path.resolve(__dirname, "node_modules/@supermap/iclient-common"),
path.resolve(__dirname, "node_modules/@supermap/iclient-leaflet"),
path.resolve(__dirname, "node_modules/elasticsearch"),
],
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}]
}
Projection
You can customize projections via L.Proj.CRS of SuperMap iClient for Leaflet. Bounds, origion, scale array, resolution array can be specified, as shown below:
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);
view source code »
For projections that are not supported or user-defined, you need to define key-value pairs through the Proj4js.defs[] static constant. Proj4js is a projection-related JavaScript script library. Please refer to the following website for details: https://trac.osgeo.org/proj4js/。
Currently, Proj4js supports following projections: 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 ");
For parameter definition of projections, please refer to https://spatialreference.org; If defined, you can search and view the parameters. For example, for EPSG:21418, the parameters are https://spatialreference.org/ref/epsg/21418/proj4/。
For a user-defined projection, you can create the projection by defining EPSGCODE and defs, where defs contains the reference projection parameters including name, projection, conversion to the WGS84 coordinate system (three parameters), major semiaxis, flatterning rate, original latitude, central meridian, standard parallels, east offset, north offset, Unit, etc.
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");
Compatible with IE 8
The 1.2.0 version of Leaflet does not support IE8 for the time being, use the 1.0.3 instead.
For better compatible with IE 8, except for leaflet.js, iclient9-leaflet.js, you still need to introduce es5-shim.
You can directly download es5-shim.js和
es5-sham.js, or refer the online addresss:
https://cdn.bootcss.com/es5-shim/4.5.9/es5-shim.js
https://cdn.bootcss.com/es5-shim/4.5.9/es5-sham.js
Add the following code before the <script> tab in the introduced leaflet.js:
<!--[if lte IE 8]>
<script src="your shim js"></script>
<script src="your sham js"></script>
<![endif]-->
Using Map Services
REST map service functions provided by SuperMap iClient for Leaflet include:
- Map layer: Supports dynamic layer locationing, dynamic layer overlay
- Map control: Map dragging, zooming and panning, feature drawing, cache switching, etc.
- Thematic maps: Unique values map, ranges map, label map, dot density map, graduated symbol map, graph map.
- Query: Distance query, geometric object query, SQL query, bounds query, nautical chart query
- Measure:Distance query and area query
Using REST Map Services
Dynamic Layer Overlay
A layer is used to load information on the map for display. For one map, you can add one or multiple layers to realize the effects the client wants. You can use addTo() to add a layer to a map. In this example, we add the map for Beijing and Tianjin area to the World map:
//Initialize map information
var map = L.map('map', {
crs: L.CRS.EPSG4326,
center: [40, 118],
maxZoom: 18,
zoom: 6
});
//initialize layer
var layerWorld = L.supermap.tiledMapLayer(DemoURL.world);
var layerJingjin = L.supermap.tiledMapLayer(DemoURL.jingjin_map, {
transparent: true,
opacity: 0.6
});
//load layer
layerWorld.addTo(map);
layerJingjin.addTo(map);
Run effects

Distance Measurement
Construct Servie Parameter Class
The measurement service parameter class provides the information required by the service request, which provides the query parameter encapsulation of the measurement. Parameters provided include geometry and unit, which are used to define the geometric objects and units of the measurement, with the code as follows:
var measureParam = new SuperMap.MeasureParameters();
//Set the vector object ({line} or {Polygon}) to measure, and geometry can obtain via initialization
measureParam.geometry = geometry;
measureParam.unit = SuperMap.Unit.METER;
Distance Measurement
Construct Servie Parameter Class
The measurement service parameter class provides the information required by the service request, which provides the query parameter encapsulation of the measurement. Parameters provided include geometry and unit, which are used to define the geometric objects and units of the measurement, with the code as follows:
var measureParam = new SuperMap.MeasureParameters();
//Set the vector object ({line} or {Polygon}) to measure, and geometry can obtain via initialization
measureParam.geometry = geometry;
measureParam.unit = SuperMap.Unit.METER;
Construct service class and send request
The measurement service class is responsible for sending requests to the server and getting the query results returned. The service class needs to specify service parameters such as URL, send request information to the server, and then request the complete event via the listener service. The results can be obtained from the event service data class, and handled according to the requirements. Please refer to the following code:
//Initialize the service class and set service request key parameters
var measureService = L.supermap.measureService(URL);
//Submit service request, pass service query parameters, get returned results and handle the results according to requirements
measureService.measureDistance(measureParam, function (serviceResult){
function doSomething(serviceResult);
});
3. Handle results
While handling the service request event, we can obtain the result information and display it, and use the form of the pop up window to show the measurement result:
function doSomething(serviceResult) {
var distance = serviceResult.result.distance,
unit = serviceResult.result.unit;
var content = "Distance: " + distance + “ ”+unit;
//Add pop up window at start point marker
marker.bindPopup(content).openPopup(marker.getLatLng());
}
Run effects

Using OGC Map Service
WMS Service
The WMS layer allows you to access layer services based on the OGC WMS Standard, including other third-party WMS services other than those from iServer. WMS Service conforms to WMS Implementation Specification provided by OGC (Open Geospatial Consortium, the Open Geographical Information Alliance), currently including WMS 1.1.1 and 1.3.0.
This section will introduce to you how to add WMS layer to display OGC map service data taking WMS_China published by SuperMap iServer as an example.
//Initialize map
var url = "https://iserver.supermap.io/iserver/services/map-china400/wms111/China";
var map = L.map('map', {
center: [0, 0],
maxZoom: 18,
zoom: 1
});
//Initialize layer
var layer =L.tileLayer.wms(url, {
layers: 'China',
format: 'image/png',
transparent: true,
noWrap: true,
});
//Load layer
layer.addTo(map);
Run effects

WMTS Service
The WMTS layer allows you to access layer services based on the OGC WMTS 1.0.0 Standard, including other third-party WMS services other than those from iServer. WMTS is first service standard to support rest from OGC. Current version is 1.0.0. Currently, three request modes are supported: HTTP KVP (Key-value Pair) mode, SOAP mode, REST mode. Note: Users need to set various types of parameters for the map request: matrixIds、layer、tilematrixSet、url and so on, where the matrixIds will be different due to the standard of the service and the scale set and needs to be set accordingly.
This section will introduce to you how to add WMTS layer to display OGC map service data taking WMTS_China published by SuperMap iServer as an example.
//Initialize map
//Resolution arrary information of the current layer
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])
})
});
//Initialize layer
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"
});
//Load layer
layer.addTo(map);
Run effects

Using Data Services
REST data services supported by SuperMap iClient for Leaflet include:
- Dataset ID Query
- Dataset Geometry Query
- Dataset Buffer Query
- Dataset SQL Query
- Dataset Editing
Using REST Data Service
Dataset ID Query
Dataset ID query queries geographic features with specified IDs in a dataset and display the results on the client. This example queries geographic features with specified IDs in the World dataset.
//Initialize map, and add event for the map
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();
});
//Handle dataset ID query
function query() {
//Dataset ID query service parameters
var idsParam = new SuperMap.GetFeaturesByIDsParameters({
IDs: [246, 247],
datasetNames: ["World:Countries"]
});
//Send the request to the server and handle the results returned from the server
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) {
//Add pop up event for the results
layer.bindPopup("ID: " + feature.properties.SMID +
"<br>" + "Country: " + feature.properties.COUNTRY);
}}).addTo(map);
});
}
Run effects

Dataset SQL Query
Dataset SQL query queries geographic vector features satisfying a specified SQL condition in a dataset and display the results on the client. This example queries geographic features with specified SMID in the World dataset.
//Initialize map, and add event for the map
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();
});
//Handle dataset SQL query
function query() {
//Dataset SQL query service parameters
var sqlParam = new SuperMap.GetFeaturesBySQLParameters({
queryParameter: {
name: "Countries@World",
attributeFilter: "SMID = 247"
},
datasetNames: ["World:Countries"]
});
//Send the request to the server and handle the results returned from the server
var url = "https://iserver.supermap.io/iserver/services/data-world/rest/data";
L.supermap.featureService(url).getFeaturesBySQL(sqlParam, function (serviceResult) {
//Display results on the map and add pop up window for the results
L.geoJSON(serviceResult.result.features).addTo(map).bindPopup('SMID = 247');
});
}
Run effects

Using Spatial Analyst Services
Spatial analysis functions supported by SuperMap iClient for Leaflet include:
- Buffer Analysis
- Overlay Analysis
- Surface Analysis
- Dynamic Segmentation
- Route Calculate Measure Services
- Route Locator Point Services
- Route Locator Line Services
Sample: Buffer Analysis
Buffer analysis is an analytical method that automatically establishes a range of regions of a certain width based on the specified distance around the point, line, and polygon features. For example, in environmental governance, a certain width is often drawn around polluted rivers to indicate contaminated areas. At airports, a range of areas are often zoned around a non residential area due to health needs.
Here we create a round buffer with the buffer radius of 10 meters around a road for Changchun data.
Set parameters for buffer analysis
//Buffer analysis parameters
dsBufferAnalystParams = new SuperMap.DatasetBufferAnalystParameters({
//The dataset name in the datasource used for buffer analysis
dataset: "RoadLine2@Changchun",
//Set the filter condition for feature set in the dataset
filterQueryParameter: new SuperMap.FilterParameter({
//Attribute filter condition
attributeFilter: "NAME='Tuanjie Road'"
}),
//Set buffer analysis common parameters
bufferSetting: new SuperMap.BufferSetting({
//Set end type, including FLAT and RROUND
endType: SuperMap.BufferEndType.ROUND,
//Left radius
leftDistance: {value: 10},
//Right radius
rightDistance: {value: 10},
//Set the number of line segments for round buffer
semicircleLineSegment: 10
})
});
Set the buffer analysis service object, which is used to pass parameters specified at the cient side to the server side and receive the data from returned from the server. When a request has been sent to the server and the server has returned the result successfully, the user can handle the results of buffer analysis from the server.
//Initialize map, and add event for the map
var baseUrl = "https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/ChangchunCityMap";
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();
});
//Define buffer analysis service
function bufferAnalystProcess(){
var serviceUrl = "https://iserver.supermap.io/iserver/services/spatialanalyst-changchun/restjsr/spatialanalyst"
var bufferServiceByDatasets = L.supermap.spatialAnalystService(serviceUrl);
//Send the request to the server and display the results returned from the server on the map
bufferServiceByDatasets.bufferAnalysis(dsBufferAnalystParams,function(serviceResult)
{
var result = serviceResult.result;
resultLayer = L.geoJSON(result.recordset.features, {color: "red"})
resultLayer.addTo(map);
});
}
Run effects

Sample: Overlay Analysis
Overlay analysis is a very important spatial analysis function in GIS. It refers to the process of generating new datasets through a series of set operations on two data sets under the unified spatial Reference system, which aims to extract the new spatial geometry information needed by the user via processing or analyzing spatial data. At the same time, the various attribute information of the data will be processed by the overlay analysis.
At present, overlay analysis is widely used in resource management, urban construction assessment, land management, agriculture, forestry, animal husbandry, statistics and other fields. The role of overlay analysis in various fields:
- Resource management is mainly used in the fields of agriculture and forestry to solve the problems of distribution, change and statistics of various resources.
- Urban construction assessment should be used to analyze the development and change of urban population, economy and construction, and the trend and law of the change.
- Land and cadastre management involves the change of land use nature, the change of plot boundary and the change of cadastral ownership, which can be accomplished efficiently with high quality under the help of GIS overlay analysis.
- Ecological and environmental management evaluation is used for regional ecological planning evaluation, environmental status assessment, environmental impact assessment, pollutant reduction and allocation of decision-making support, etc.
- Geoscience research and application is used for topographic analysis, watershed analysis, land use research, economic geography research, spatial statistical analysis, cartography, etc.
Here we overlay the administrative boundary of Beijing and Tianjin area and that of neighboring areas.
Set overlay analysis parameters
//Set overlay analysis parameters
var dsOverlayAnalyParams = new SuperMap.DatasetOverlayAnalystParameters({
sourceDataset: "BaseMap_R@Jingjin", //The name of the source dataset of overlay analysis
operateDataset: "Neighbor_R@Jingjin", //The name of the operate dataset of overlay analysis
tolerance: 0, //Tolerance
operation: SuperMap.OverlayOperationType.UNION //The type of overlay analysis
});
Set the overlay analysis service object, which is used to pass parameters specified at the cient side to the server side and receive the data from returned from the server. When a request has been sent to the server and the server has returned the result successfully, the user can handle the results of overlay analysis from the server.
//Initialize map, and set event for the map
var baseUrl = "https://iserver.supermap.io/iserver/services/map-jingjin/rest/maps/JingjinPopulationDistribution_ThematicMap",
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();
});
//Define overlay analysis service
function overlayAnalystProcess() {
var serviceUrl = "https://iserver.supermap.io/iserver/services/spatialanalyst-sample/restjsr/spatialanalyst";
var overlayAnalystService = L.supermap.spatialAnalystService(serviceUrl);
//Send the request to the server and display the results returned from the server on the map
overlayAnalystService.overlayAnalysis(dsOverlayAnalyParams, function(serviceResult) {
var result = serviceResult.result;
var resultLayer = L.geoJSON(result.recordset.features)
resultLayer.addTo(map);
);
}
Run effects

Sample: Surface Analysis
Surface analysis refers to mining the hidden information contained in the original data by analyzing datasets or geometric objects. Surface analysis includes extracting isolines and extracting isoregions. Isolines are lines connected with adjacent points with same values, commonly used for contour lines for height, depth, temperature, precipitation, etc. The distribution of isolines reflects the change of the value on the grid surface, and the denser the contour lines are, the more drastic the change of the grid surface values. At places where the contour distribution is sparse, the change of grid surface values is smaller. By extracting isolines, we can find places where the elevation, temperature or precipitation is the same. Meanwhile, the distribution of isolines can also reflect where the value change is steep or gentle. The isoregions is composed by closing adjacent contour lines. The change of the isoregions can intuitively indicate the change between adjacent isolines, such as elevation, precipitation, temperature or atmospheric pressure. Places where the elevation, precipitation or temperature is equivalent can be obtained by extracting the isoregions.
This section will introduce how to extract contour lines based on temperature resample points of China.
Set surface analysis parameters
//Set clip area
var region = L.polygon([[4010338,0],[4010338,1063524],[3150322,1063524],[3150322,0]]);
//Set surface analysis parameters
var extractParams = new SuperMap.SurfaceAnalystParametersSetting({
datumValue: 0, //The datum value in surface analysis
interval: 2, //The interval value
resampleTolerance: 0, //The resample tolerance
smoothMethod: SuperMap.SmoothMethod.BSPLINE, //The method used for smoothing
smoothness: 3, //The smoothness of contour lines
clipRegion: region //The clip object
});
//The surface analysis parameters
var surfaceAnalystParams = new SuperMap.DatasetSurfaceAnalystParameters({
extractParameter: extractParams, //The surface analysis parameters
dataset: "SamplesP@Interpolation", //The name of the source dataset in overlay analysis
resolution: 3000, //The resoluton of intermediate results
zValueFieldName: "AVG_TMP" //The name of the field used for extraction
});
Set the surface analysis service object, which is used to pass parameters specified at the cient side to the server side and receive the data from returned from the server. When a request has been sent to the server and the server has returned the result successfully, the user can handle the results of surface analysis from the server.
//Initialize map, and add event for the map
var baseUrl = "https://iserver.supermap.io/iserver/services/map-temperature/rest/maps/ChinaTemperatureMap";
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();
});
//Process surface analysis service
function surfaceAnalystProcess() {
//Initialize surface analysis service instance
var serviceUrl = "https://iserver.supermap.io/iserver/services/spatialanalyst-sample/restjsr/spatialanalyst" ;
var surfaceAnalystService = L.supermap.spatialAnalystService(serviceUrl);
//Send the request to the server and process the resullts
surfaceAnalystService.surfaceAnalysis(surfaceAnalystParams, function (serviceResult) {
L.geoJSON(serviceResult.result.recordset.features, {weight: 3}).addTo(map);
});
}
Run effects

Sample: Dynamic Segmentation
Dynamic segmentation is developed on linear reference. It employs two data structures: route dataset and event table dataset. In real practise, many geographic positions are recorded as the events of features along the line. For example, we tell you that an accident happened in 500m west to the No. 32 corner. Sometimes, over-accurate figures are useless for us in our daily life. However, the relative positions points or lines can help us get the information we want at ease. Linear reference can associate each part of the linear feature to different attribute values under the conditions of not splitting the linear feature into sections. The thought of linear reference can be applied in linear data collection like roads, railways, rivers, etc., public transportation system management, road quality management as well as communication and distribution networks (such as power grids, telephone lines, TV cables, water supply and drainage pipes, etc.).
This section introduces to you how to show the road traffic (blocked/congested/expedite) in real-time on the client side based on dynamic segmentation technology to prompt motorists to avoid entering the congested road and choose the appropriate route using data for Changchun city road map as the sample data.
Set parameters including DataReturnOption and generateSpatialDataParams for dynamic segmentation on the client side.
//Configure dynamic segmentation parameters
var generateSpatialDataParams = new SuperMap.GenerateSpatialDataParameters({
routeTable: "RouteDT_road@Changchun",//Route dataset
routeIDField: "RouteID",//The route ID
eventTable: "LinearEventTabDT@Changchun",//The event table used to generate spatial data
eventRouteIDField: "RouteID",//The route ID of the event table used to generate spatial data
measureField: "",//The measure field of the event table used to generate spatial data
measureStartField: "LineMeasureFrom",//The from field of the event table
measureEndField: "LineMeasureTo",//The to field of the event table
measureOffsetField: "",//The offset field for measure values
errorInfoField: "",//The error message field
//Set DataReturnOption
dataReturnOption: new SuperMap.DataReturnOption({
//Set the maximum number of records allowed to be returned
expectCount: 1000,
//Set result dataset identification. Because dataReturnMode is set to SuperMap.REST.DataReturnMode.DATASET_ONLY, only the name of the dataset will be returned
dataset: "generateSpatialData@Changchun",
//If the user-named result dataset name is the same as the existing dataset, delete the existing data set
deleteExistResultDataset: true,
//Set the data return mode to DATASET_ONLY
dataReturnMode: SuperMap.DataReturnMode.DATASET_ONLY
})
});
Set the dynamic segmentation service object, which is used to pass parameters specified at the cient side to the server side and receive the data from returned from the server. When a request has been sent to the server and the server has returned the result successfully, the user can handle the results of dynamic segmentation from the server.
//Initialize map, and set event for the map
var baseUrl = "https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/ChangechunCityMap",
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();
});
//Configure dynamic segmentation service
function generateSpatialDataAnalystProcess(){
var serviceUrl = "https://iserver.supermap.io/iserver/services/spatialanalyst-changchun/restjsr/spatialanalyst"
var generateSpatialDataService = L.supermap.spatialAnalystService(serviceUrl);
//Send the request to the server and display the results on the client side as thematic map
generateSpatialDataService.generateSpatialData(generateSpatialDataParams, function () {
//Display the results on the client side as thematic map
showAnalysisResult_ThemeGridUnique();
});
//When the data is returned, it will be displayed on the client side as thematic map
function showAnalysisResult_ThemeGridUnique() {
//Create a thematic map instance
themeService = L.supermap.themeService(baseUrl);
//Configure thematic map styles
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
});
//Configure thematic map items
var themeUniqueIteme1, themeUniqueIteme2, themeUniqueIteme3;
themeUniqueIteme1 = new SuperMap.ThemeUniqueItem({
unique: "Blocked",
style: style1
});
themeUniqueIteme2 = new SuperMap.ThemeUniqueItem({
unique: "Congested",
style: style2
});
themeUniqueIteme3 = new SuperMap.ThemeUniqueItem({
unique: "Expedite",
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);
}
});
}
Run effects

Sample: Route Calculate Measure Services
Route Calculate Measure calculates the M-value of a point to the starting point of the route. For example, a user may want to know where an accident occurred to determine the distance of the point from a certain intersection.
Here we calculate the distance from an accident point to the road intersection (route ID 1690). The sample data used is Changchun data.
Interface usage for Route Calculate Measure Service is as follows:
You need to first initialize the map before the Route Calculate Measure operation.
//Initialize map, and set event for the map
var baseUrl = "https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/ChangchunCityMap";
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();
});
After the map loading is completed, we will perform the Route Calculate Measure operation. First, we need to get the route object according to the RouteID, and then proceed to subsequent operation.
function routeCalculateMeasureProcess() {
//Set SQL query parameters
var queryBySQLParams = new SuperMap.QueryBySQLParameters({
queryParams: [
new SuperMap.FilterParameter({
name: "RouteDT_road@Changchun",
attributeFilter: "RouteID=1690"
})
]
});
//Create SQL service
var queryBySQLService = L.supermap.queryService(baseUrl);
//Send the request to the server and handle the results returned from the server
queryBySQLService.queryBySQL(queryBySQLParams, function (serviceResult) {
var resultLayer = L.geoJSON(serviceResult.result.recordsets[0].features,
{color: "red"}).addTo(map);
//Extract the points that form the route to construct the parameter 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);
//Select one query point (the 8th point in the array) from the points that compose the route and add it to the map
var marker= L.circleMarker([routeObj[7][1], routeObj[7][0]],
{radius: 3, color: 'black'}).addTo(map);
//Create routeCalculateMeasureService
var serviceUrl = "https://iserver.supermap.io/iserver/services/spatialanalyst-changchun/restjsr/spatialanalyst";
var routeCalculateMeasureService = L.supermap.spatialAnalystService(serviceUrl);
//Set parameters
var routeCalculateMeasureParameters = new SuperMap.RouteCalculateMeasureParameters({
"sourceRoute": routeLine,Route Type
"point": L.point(routeObj[7][0], routeObj[7][1]),//Query point
"tolerance": 10,
"isIgnoreGap": false
});
//Send the request to the server and handle the results returned from the server routeCalculateMeasureService.routeCalculateMeasure ( routeCalculateMeasureParameters, function (serviceResult) {
//Add pop up window for the query results and display the obtained M value
marker.bindTooltip("The M value obtained is: " + serviceResult.result.measure + "", {direction:"top",offset:L.point(0,-5)}).openTooltip();
});
});
}
Run effects

Sample: Route Locator Point Services
Route Locator Point determines the point according to the M value. The application scenario is opposite to Route Calculate Measure. It will be used to determine the precise coordinates of an accidient position when we already know the M value from the point to the raod intersection.
Here we will determine the precise coordinates of an accidient position when we already know the M value from the point to the raod intersection is 10 KM on the route with the ID of 1690. The sample data used here is Changchun data.
You need to first initialize the map before the Route Locator Point operation.
//Initialize map, and add event for the map
var baseUrl = "https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/ChangchunCityMap";
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();
});
After the map loading is completed, we will perform the Route Locator Point operation. First, we need to get the route object according to the RouteID, and then proceed to subsequent operation.
function routeLocatorProcess() {
//Set SQL query service parameters
queryBySQLParams = new SuperMap.QueryBySQLParameters({
queryParams: [
new SuperMap.FilterParameter({
name: "RouteDT_road@Changchun",
attributeFilter: "RouteID=1690"
})
]
});
//Create query service
var queryBySQLService = L.supermap.queryService(baseUrl);
//Send the request to the server, handle the results returned from the server, and display the handled results on the map
queryBySQLService.queryBySQL(queryBySQLParams, function (serviceResult) {
var resultLayer = L.geoJSON(serviceResult.result.recordsets[0].features,
{color: "red"}).addTo(map);
//Extract the points that form the route to construct polyline of 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]])
}
var routeLine = L.polyline(pointsList);
//Handle Route Locator Point service
//Set Route Locator Point parameters
var routeLocatorParams_point = new SuperMap.RouteLocatorParameters({
"sourceRoute": routeLine, //The route object
"type": "POINT", //Type, point or line
"measure": 200, //M value
"offset": 0, //Offset
"isIgnoreGap": true //Whether to ignore distance between child objects
});
//Create spatial analysis service
var serviceUrl =
"https://iserver.supermap.io/iserver/services/spatialanalyst-changchun/restjsr/spatialanalyst";
var routeLocatorService = L.supermap.spatialAnalystService(serviceUrl);
//Send the request to the server and display the results on the client side after handling
routeLocatorService.routeLocate(routeLocatorParams_point, function (serviceResult) {
var layer=L.geoJSON(serviceResult.result.resultGeometry).addTo(map);
//Add pop up window
layer.bindTooltip("Point with M value " + routeLocatorParams_point.measure + " found" , {direction:"top", offset:L.point(0,-5)}).openTooltip();
});
});
}
Run effects

Sample: Route Locator Line Services
Route Locator Line determines the line object on the route according to the specified range. For example, you need to know the precise position of a line segment when we know there is a line segment blocked.
Here we introduce how to determine precise position of a line segment if we already know the measure values of the line segment to the road intersection are 10km to 800km.
You need to first initialize the map before the Route Locator Line operation.
//Initialize map, and add event for the map
var baseUrl =
"https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/ChangchunCityMap",
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();
});
After the map loading is completed, we will perform the Route Locator Line operation. First, we need to get the route object according to the RouteID, and then proceed to subsequent operation.
function routeLocatorProcess () {
//Set SQL query service parameters
queryBySQLParams = new SuperMap.QueryBySQLParameters({
queryParams: [
new SuperMap.FilterParameter({
name: "RouteDT_road@Changchun",
attributeFilter: "RouteID=1690"
})
]
});
//Create query service
var queryBySQLService = L.supermap.queryService(baseUrl);
//Send the request to the server, handle the results returned from the server, and display the handled results on the map
queryBySQLService.queryBySQL(queryBySQLParams, function (serviceResult) {
var resultLayer = L.geoJSON(serviceResult.result.recordsets[0].features,
{color: "red"}).addTo(map);
//Extract the points that form the route to construct polyline of 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]])
}
var routeLine = L.polyline(pointsList);
//Handle Route Locator Line
//Set Route Locator Line parameters
var routeLocatorParams_line = new SuperMap.RouteLocatorParameters({
"sourceRoute": routeLine, //The route object
"type": "LINE", //Type, point or line
"startMeasure": 10, //The from value of the line
"endMeasure": 800, //The to value of the line
"isIgnoreGap": true //Whether to ignore distance between child objects
});
//Create spatial analysis service
var serviceUrl =
"https://iserver.supermap.io/iserver/services/spatialanalyst-changchun/restjsr/spatialanalyst";
var routeLocatorService = L.supermap.spatialAnalystService(serviceUrl);
//Send the request to the server and display the results on the client side after handling
routeLocatorService.routeLocate(routeLocatorParams_line, function (serviceResult) {
var resultLayer1 = L.geoJSON(serviceResult.result.resultGeometry).addTo(map);
})
}
Run effects

Using Traffic Network Analysis Service
Traffic network analysis functions supported by SuperMap iClient for Leaflet include:
- Optimal Path Analysis
- Service Area Analysis
- Travelling Salesman Analysis
- Closest Facility Analysis
- Location Allocation Analysis
- Multiple Travelling Salesmen Analysis
Sample: Optimal Path Analysis
The optimal path analysis is to find the route with the minimum impedance between two points in the network. It is necessary to access nodes in the network according to the selection order of nodes. Minimum Impedance can be the shortest time, the lowest cost, the best scenery, the best road conditions, the least bridges, the minimum toll stations, most villages passed and so on.
Here we introduce how to get the optimal path between two specified points on the map.
Set findPathParams, including common parameters for traffic network analysis, stops passed, etc.
//Traffic network analysis result parameters
var resultSetting = new SuperMap.TransportationAnalystResultSetting({
returnEdgeFeatures: true, //Whether to include edge collection in the results
returnEdgeGeometry: true, //Whether to include collection object information in the returned edge feature collection
returnEdgeIDs: true, //Whether to include ID collection of passed edges in the returned results
returnNodeFeatures: true, //Whether to include node feature collection in the returned results
returnNodeGeometry: true, //Whether to include collection object information in the returned node feature collection
returnNodeIDs: true, //Whether to include ID collection of passed nodes in the returned results
returnPathGuides: true, //Whether to include path guides collection in the returned results
returnRoutes: true//Whether to include route object collection in the returned results
});
//Traffic network analysis common parameters
var analystParameter = new SuperMap.TransportationAnalystParameter({
resultSetting: resultSetting, //The contents of the analysis results
weightFieldName: "length"//Name of the impedance field
});
//Optimal path analysis parameters
var findPathParams = new SuperMap.FindPathParameters({
isAnalyzeById: false, //Whether to specify route analysis nodes by node ID
//The array of nodes or facility points passed in optimal path analysis
nodes: [L.latLng(-3000, 4000), L.latLng(-2500, 5500), L.latLng(-4000, 6900)],
hasLeastEdgeCount: false, //Whether to perform optimal path analysis according to least edges
parameter: analystParameter//Traffic network analysis common parameters
});
Send the request for optimal path analysis to the server and parse the serviceResult returned from the server if the analysis successful. Finally, display the route on the map and provide the path guides.
//Initialize map, and add event for the map
var baseUrl = "https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/ChangchunCityMap";
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();
});
//Define optimal path analysis service
function findPathProcess(){
//Add stops
var marker1 = L.marker([-3000, 4000]).addTo(map);
marker1.bindPopup("Stop 1");
var marker2 = L.marker([-2500, 5500]).addTo(map);
marker2.bindPopup("Stop 2");
var marker3 = L.marker([-4000, 6900]).addTo(map);
marker3.bindPopup("Stop 3");
//Set icon
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);
//Send the request to the server and display the results on the client side after handling and analysis
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);
})
});
}
Run effects

Sample: Service Area Analysis
Service area analysis finds the serving area of a supply center in the network. For example, we can calculate the serving area within 30 minutes for a point in the network. Time cost for all points to the specified point within the result area will be less than 30 minutes.
Here we will do buffer analysis for center points selected. We choose the incrementing value 400, 500, 600... as service radius for the center points according to the selection order.
The usage of interfaces for service area analysis:
Set findServiceAreasParams, including traffic network analysis common parameters, passed stops, etc.
//Add center points
var marker = L.marker([-3375, 5605]).addTo(map);
//Traffic network analysis result parameters
var resultSetting = new SuperMap.TransportationAnalystResultSetting({
returnEdgeFeatures: true,//Whether to include edge collection in the results
returnEdgeGeometry: true,//Whether to include collection object information in the returned edge feature collection
returnEdgeIDs: true,//Whether to include ID collection of passed edges in the returned results
returnNodeFeatures: true,//Whether to include node feature collection in the returned results
returnNodeGeometry: true,//Whether to include collection object information in the returned node feature collection
returnNodeIDs: true,//Whether to include ID collection of passed nodes in the returned results
returnPathGuides: true,//Whether to include path guides collection in the returned results
returnRoutes: true//Whether to include route object collection in the returned results
};
//Traffic network analysis common parameters
var analystParameter = new SuperMap.TransportationAnalystParameter({
resultSetting: resultSetting,//The contents of the analysis results
weightFieldName: "length"//Name of the impedance field
});
var findServiceAreasParams = new SuperMap.FindServiceAreasParameters({
centers: [marker.getLatLng()],//Service stop array
isAnalyzeById: false,//Whether to specify route analysis nodes by node ID
parameter: analystParameter,//Traffic network analysis common parameters
weights: weightsArray//The impedance radius of each stop to provide service
});
Define the service area analysis service object to pass the parameters specified by the client to the server and receive the result data. If the client has sent the request and the server has returned the results successfully, the user can receive the analysis results and handle the results.
//Initialize map, and add event for the map
var baseUrl = "https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/ChangchunCityMap";
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();
});
//Define service area analysis service
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];
//Send the request to the server and handle the results returned from the server
service.findServiceAreas(findServiceAreasParams, function (serviceResult) {
var result = serviceResult.result;
result.serviceAreaList.map(function (serviceArea) {
resultLayer.addLayer(L.geoJSON(serviceArea.serviceRegion));
});
});
}
Run effects

Sample: Travelling Salesman Analysis
The travelling salesman analysis is to find the path that passes through a specified set of points. It is unordered path analysis. The traveler can decide the order to pass the nodes to achieve minimum (or closest to minimum) impedance.
For travelling salesman analysis, if a termination point is specified, the traveler must access termination point last, and the order of other points can be determined by the traveler itself. Here we will introduce how to perform travelling salesman analysis. The sample data used is Changchun data.
Set findTSPPathsParams, including traffic network analysis common parameters, passed stops, etc.
//Traffic network analysis result parameters
var resultSetting = new SuperMap.TransportationAnalystResultSetting({
returnEdgeFeatures: true,//Whether to include edge collection in the results
returnEdgeGeometry: true,//Whether to include collection object information in the returned edge feature collection
returnEdgeIDs: true,//Whether to include ID collection of passed edges in the returned results
returnNodeFeatures: true,//Whether to include node feature collection in the returned results
returnNodeGeometry: true,//Whether to include collection object information in the returned node feature collection
returnNodeIDs: true,//Whether to include ID collection of passed nodes in the returned results
returnPathGuides: true,//Whether to include path guides collection in the returned results
returnRoutes: true//Whether to include route object collection in the returned results
};
//Traffic network analysis common parameters
var analystParameter = new SuperMap.TransportationAnalystParameter({
resultSetting: resultSetting,//The contents of the analysis results
weightFieldName: "length"//Name of the impedance field
});
var findTSPPathsParams = new SuperMap.FindTSPPathsParameters ({
isAnalyzeById: false,//Whether to specify passed nodes by Node ID
nodes: nodeArray,//The array of passed nodes for travelling salesman analysis. The array can be array of coordinates or IDs of points
endNodeAssigned: false,//Whether to specify termination point
parameter: analystParameter//Traffic network analysis common parameters
});
Define the travelling salesman analysis service object to pass the parameters specified by the client to the server and receive the result data. If the client has sent the request and the server has returned the results successfully, the user can receive the analysis results and handle the results.
//Initialize map, and set event for the map
var baseUrl = "https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/ChangchunCityMap";
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();
});
//Multiple travelling salesmen analysis
function findTSPPathsProcess() {
//Add stops
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);
//Add pop up windows for supply centers
marker4.bindPopup("Retail Stop 1");
marker5.bindPopup("Retail Stop 2");
marker6.bindPopup("Retail Stop 3");
//Create multiple travelling salesmen analysis service instance
var serviceUrl = "https://iserver.supermap.io/iserver/services/transportationanalyst-sample/rest/networkanalyst/RoadNet@Changchun";
var findTSPPathsService = L.supermap.networkAnalystService(serviceUrl);
//Send the request to the server and handle the results returned
findTSPPathsService.findTSPPaths(findTSPPathsParams, function (serviceResult) {
var result = serviceResult.result;
result.tspPathList.map(function (result) {
L.geoJSON(result.route).addTo(map);
});
});
}
Run effects

Sample:Closest Facility Analysis
Closest facility analysis finds the one or more facility points from the event point with the least cost in the network after giving one event point and a set of facility points. The results contain the optimal path, cost, and direction of travel from the event point to the facility point (or from the facility point to the event point). For example, the incident point is a traffic accident, and facility points are hospitals around. The closest facility analysis is to find the nearest hospitals which can be arrived in 10 minutes. In this case, the position where the accident happens is an event point, and the surrounding hospitals are facility points. Closest facility analysis is actually a path analysis, therefore, you can set barrier edges and nodes in the network to indicates that these edges or nodes can not be crossed.
Here we will introduce how to find the closest hospital for an accident marked on the map. The sample data used here is Changchun data.
Set closest facility analysis parameters, including traffic network analysis common parameters, event points, facility points, searching radius, etc.
//Traffic network analysis result parameters
var resultSetting = new SuperMap.TransportationAnalystResultSetting({
returnEdgeFeatures: true,//Whether to include edge collection in the results
returnEdgeGeometry: true,//Whether to include collection object information in the returned edge feature collection
returnEdgeIDs: true,//Whether to include ID collection of passed edges in the returned results
returnNodeFeatures: true,//Whether to include node feature collection in the returned results
returnNodeGeometry: true,//Whether to include collection object information in the returned node feature collection
returnNodeIDs: true,//Whether to include ID collection of passed nodes in the returned results
returnPathGuides: true,//Whether to include path guides collection in the returned results
returnRoutes: true//Whether to include route object collection in the returned results
};
//Traffic network analysis common parameters
var analystParameter = new SuperMap.TransportationAnalystParameter({
resultSetting: resultSetting,//Contents of the returned results
turnWeightField: "TurnCost",//Name of the turn weight field
weightFieldName: "length" //Name of the impedance field
});
//Closest facility analysis parameters
var findClosetFacilitiesParams = new SuperMap.FindClosestFacilitiesParameters({
//Event point, which is generally the position of the event where facility service is required
event: L.latLng(-3700, 5000),
//The number of facility number to be queried
expectFacilityCount: 1,
//Facility point collection, which is generally the collection of positions of facilities that offer the service
facilities: [L.latLng(-3500, 2500), L.latLng(-2500, 5500), L.latLng(-4000, 7000)],
//Whether the event point and facility points are specified by Node IDs
isAnalyzeById: false,
//Traffic network analysis common parameters
parameter: analystParameter
});
Define the closest facility analysis service object to pass the parameters specified by the client to the server and receive the result data. If the client has sent the request and the server has returned the results successfully, the user can receive the analysis results and handle the results.
//Initialize map, and set event for the map
var baseUrl = "https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/ChangchunCityMap";
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();
});
//Set closest facility analysis service
function findClosetFacilitiesProcess(){
//Add facility points
var marker1 = L.marker([-3500, 2500]).addTo(map);
marker1.bindPopup("Facility point 1");
var marker2 = L.marker([-2500, 5500]).addTo(map);
marker2.bindPopup("Facility point 2");
var marker3 = L.marker([-4000, 7000]).addTo(map);
marker3.bindPopup("Facility point 3");
//Add event points
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("Event point");
//Create closest facility analysis service instance
var serviceUrl = "https://iserver.supermap.io/iserver/services/transportationanalyst-sample/rest/networkanalyst/RoadNet@Changchun";
var findClosetFacilitiesService = L.supermap.networkAnalystService(serviceUrl);
//Send request to the server and handle the returned results
findClosetFacilitiesService.findClosestFacilities(findClosetFacilitiesParams, function (serviceResult) {
var rersult = serviceResult.result;
rersult.facilityPathList.map(function (result) {
resultLayer = L.geoJSON(result.route).addTo(map);
});
});
}
Run effects

Sample: Location Allocation Analysis
Allocation and Location is to find the optimal location from multiple candidate locations for a facility, by matching the supply and demand based on the objectives and constraints. The Allocation and Location analysis can be applied to the applications such as locating a restaurant, a school, an airport, etc.
Set location-allocation analysis parameters, including traffic network analysis common parameters, passed stops, etc.
//Resource center type, which can be fixed or optional
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,//The max cost of resource supply center
nodeID: 139,//The node ID of resource supply center
resourceValue: 100,//The maximum amount of service or quantity of goods a resource supply center can provide
type: supplyCenterType_OPTIONALCENTER//Type of resource center
}),
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
})
];
//Create FindLocationParameters instance
var findLocationParams = new SuperMap.FindLocationParameters({
expectedSupplyCenterCount: 8, //Number of resource centres expected
isFromCenter: false, //Whether to start allocating resources from supply center
nodeDemandField: "Demand", //Node demand field
turnWeightField: "TurnCost", //Turn weight field
weightName: "length", //Name of the impedance field
supplyCenters: supplyCenters //Supply center collection, required
});
Define the location-allocation analysis service object to pass the parameters specified by the client to the server and receive the result data. If the client has sent the request and the server has returned the results successfully, the user can receive the analysis results and handle the results.
//Initialize map, and set event for the map
var baseUrl = "https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/ChangchunCityMap";
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();
});
//Handle location allocation servie results
function findLocationProcess() {
//Add facility points
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);
//Create location allocation analysis service instance
var serviceUrl = "https://iserver.supermap.io/iserver/services/transportationanalyst-sample/rest/networkanalyst/RoadNet@Changchun";
var findLocationService = L.supermap.networkAnalystService(serviceUrl);
//Send request to the server and handle the returned results
findLocationService.findLocation(findLocationParams, function (serviceResult) {
L.geoJSON(serviceResult.result.demandResults, {
pointToLayer: function (geoJsonPoint, latlng) {
return L.circleMarker(latlng, {radius: 1, color: "green"});
}
}).addTo(map);
});
}
Run effects

Sample: Multiple Travelling Salesmen Analysis
Multipel travelling salemen analysis is to find the most effective and economic path for the logistics centers to deliver goods to the destinations through a network. Unlike the Path Finding analysis, the Logistics Vehicle Routing Analysis often has more than one start point, that is the logistics centers, and more than one predefined destinations. The purpose of the analysis is to find the paths from the logistics centers to the destinations with the minimum cost in total, or find the path for each logistics center with the minimum cost.
The results of the multipel travelling salemen analysis will contain the destination responsible by each distribution center, the order of distribution of goods to all destinations, and the corresponding route, which can ensure the minimum cost for each distribution center, or the minimum total cost of all distribution centers.
Here we analyze the distribution routes of each warehouse distribution center to the user-designated retail stations using the multiple travelling salesmen analysis and travelling salesman analysis. The route with minimum cost for the quality inspector to check the goods regularly at each retail station will be given. The sample data used here is Changchun data.
Set findMTSPPathsParams, including traffic network analysis common parameters, supply center collection, supply destination collection, distribution mode, etc.
//Traffic network analysis result parameters
var resultSetting = new SuperMap.TransportationAnalystResultSetting({
returnEdgeFeatures: true,//Whether to include edge collection in the results
returnEdgeGeometry: true,//Whether to include collection object information in the returned edge feature collection
returnEdgeIDs: true,//Whether to include ID collection of passed edges in the returned results
returnNodeFeatures: true,//Whether to include node feature collection in the returned results
returnNodeGeometry: true,//Whether to include collection object information in the returned node feature collection
returnNodeIDs: true,//Whether to include ID collection of passed nodes in the returned results
returnPathGuides: true,//Whether to include path guides collection in the returned results
returnRoutes: true//Whether to include route object collection in the returned results
};
//Traffic network analysis common parameters
var analystParameter = new SuperMap.TransportationAnalystParameter({
resultSetting: resultSetting,//The contents of the analysis results
weightFieldName: "length"//Name of the impedance field
});
//Multiple travelling salesmen analysis parameters
var findMTSPPathsParams = new SuperMap.FindMTSPPathsParameters({
//Supply center collection
centers: [L.latLng(-5500, 6000), L.latLng(-2500, 5500), L.latLng(-3500, 2500)],
//Whether to specify supply centers and destinations via node ID
isAnalyzeById: false,
//Supply destination collection
nodes: [L.latLng(-5000, 5000), L.latLng(-2800, 8000)],
//Whether the distribution mode is Least Total Cost
hasLeastTotalCost: true,
//Traffic network analysis common parameters
parameter: analystParameter
});
Obtain the optimal routes from the distribution centers to distribution destinations by submitting the request parameters of logistic distribution analysis to the server, and parse the returned results from the server.
//Initialize map, and set event for the map
var baseUrl = "https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/ChangchunCityMap";
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();
});
//Handle multipel travelling salemen analysis results
function findMTSPPathsProcess() {
//Add distribution centers
var marker1 = L.marker([-5500, 6000]).addTo(map);
var marker2 = L.marker([-2500, 5500]).addTo(map);
var marker3 = L.marker([-3500, 2500]).addTo(map);
//Add pop up windows for supply centers
marker1.bindPopup("Distribution center 1");
marker2.bindPopup("Distribution center 2");
marker3.bindPopup("Distribution center 3");
//Add destinations
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);
//Add pop up windows for supply centers
marker4.bindPopup("Destination 1");
marker5.bindPopup("Destination 2");
//Create multipel travelling salemen analysis service instance
var serviceUrl = "https://iserver.supermap.io/iserver/services/transportationanalyst-sample/rest/networkanalyst/RoadNet@Changchun";
var findMTSPPathsService = L.supermap.networkAnalystService(serviceUrl);
//Send the request to the server and handle the returned results
findMTSPPathsService.findMTSPPaths(findMTSPPathsParams, function (serviceResult) {
var result = serviceResult.result;
result.pathList.map(function (result) {
L.geoJSON(result.route, {color: "green"}).addTo(map);
});
});
}
Run effects

Using Traffic Transfer Analysis Service
Traffic Transfer Analysis is introduced below:
- Define start stop and end stop query function.
- Perform the traffic transfer query. First of all, we must set the traffic transfer parameters on the client side, define the traffic transfer service, and then send the request to the server. When the results are returned to the cient from the server, the client needs to parse the results and display the results.
Here we introduce how to perform traffic transfer analysis using the bus line data monitored using the Changchun road data.
1. Query traffic transfer solutions
Traffic solution query: This method returns all bus solutions, and the specific route information can be acquired depending on the information presented in the solution. First, you need to set the traffic transfer parameters, including solutionCount, transferTactic, transferPreference, walkingRatio, points, define the traffic transfer service function, Send a request to the server, and parse the traffic transfer result data returned from the server.
var map, startMarker, endMarker, tempRedLayer, tempMarker,
routeFeatureGroup, paths = {transSolutions: null, solutions: null}, info,
baseUrl = "https://iserver.supermap.io/iserver/services/map-changchun/rest/maps/ChangchunCityMap",
serviceUrl = "https://iserver.supermap.io/iserver/services/traffictransferanalyst-sample/restjsr/traffictransferanalyst/Traffic-Changchun";
//Initialize map
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);
//Set start point
startMarker = L.marker([-5527.73795456, 3111.42533851]).addTo(map)
.bindTooltip("Start point", {
offset: L.point([0, -10]),
direction: "top",
permanent: true
}).openTooltip();
//Set end point
endMarker = L.marker([-4270.0725196, 6055.3431955]).addTo(map)
.bindTooltip("End point", {
offset: L.point([0, -10]),
direction: "top",
permanent: true
}).openTooltip();
routeFeatureGroup = L.featureGroup().addTo(map); //Establish temporary stop layer
tempRedLayer = L.featureGroup().addTo(map); //Establish temporary bus line layer
initResultInfoWin(); //Initialize message box
execTransSolutionsQuery('LESS_TIME'); //Least transfer time query
//Initialize message box
function initResultInfoWin() {
info = L.control({position: 'topright'}); //Display the message box at the top rigt corner
info.onAdd = function () {
this._div = L.DomUtil.create('div', 'panel panel-primary');
info.update();
handleMapEvent(this._div, this._map);
return this._div;
};
//Map event
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();
});
}
//Message box content update
info.update = function (transSolutions, transGuide) {
if (!transSolutions) {
return;
}
var solution, lines, line, dispStatus = "block";
$("<div class='panel-heading' style='background:steelblue;color: honeydew'>Start point: Auto Repair Shop End point: Zhongan Mansion<br/>Transfer Solution (Least Time)</div>").appendTo(this._div);
for (var i = 0, iLen = transSolutions.length; i < iLen; i++) {
solution = transSolutions[i];
//Display solution
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'>Solution " + (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);
//Display table of solution 1 by default
if (i === 0) {
fillTransferInfo(transGuide, transSolutions, 0).appendTo(list);
setPopup();
}
}
//Display the corresponding table while clicking a solution
bindSolutionsClickEvent();
};
info.addTo(map);
}
//Display table of solution indexX
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> Walk to: <a class='busLink'><span style='display:none'>" + item.endPosition.x + "," + item.endPosition.y + "</span>" + item.endStopName + "</a></td>").appendTo(tr2);
$("<td>" + parseInt(item.distance) + " m </td>").appendTo(tr2);
} else {
var otherLines = transSolutions[indexX].linesItems[indexY],
links = "";
if (otherLines && otherLines.lineItems.length > 1) {
links = "</br> or take: "
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> Take <a class='busLink'>" + item.lineName + "<span style='display:none'>" + pointStr + "</span></a>, at <a class='busLink'><span style='display:none'>" + item.endPosition.x + "," + item.endPosition.y + "</span>" + item.endStopName + "</a> Get off " + links + "</td>").appendTo(tr2);
$("<td>" + item.passStopCount + " stop </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;
}
//Define execTransSolutionsQuery
function execTransSolutionsQuery(tactic) {
//Clear results of the previous solution
info.remove();
paths.points = [26, 180];
//Configure TransferSolutionParameters
var params = new SuperMap.TransferSolutionParameters({
solutionCount: 6,//The maximum transfer guide count
transferTactic: tactic,//Type of bus transfer strategy
walkingRatio: 10,//Weight ratio of walking and bus consumption
points: paths.points //Starting point coordinates
});
var serviceUrl = "https://iserver.supermap.io/iserver/services/traffictransferanalyst-sample/restjsr/traffictransferanalyst/Traffic-Changchun";
//Send the request to the server and handle the results returned from the server
L.supermap.trafficTransferAnalystService(serviceUrl)
.analysisTransferSolution(params, function (serviceResult) {
if (serviceResult.error) {
alert("Error: " + serviceResult.error.errorMsg);
}
transferSolutionsSucceed(serviceResult.result);
});
}
//The returned results when implemented successfully
function transferSolutionsSucceed(result) {
clearLayer();
info.addTo(map);
//Overlay symbol information on the map
//transGuide:Records the traffic transfer guidance scheme from the starting point to the terminating point
//transGuide is composed of objects of the TransferGuideItem type
//Each TransferGuideItem can be a transfer segment or walking route. The type of object can return the number of items in transGuide
//The total distance and cost can be guided according to TransferGuideItem
//transSolutions: The transfer times are the same in all bus routes within a transfer scheme.
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);
}
//Clear all result layers
function clearLayer() {
if (routeFeatureGroup) {
routeFeatureGroup.clearLayers();
}
if (tempRedLayer) {
tempRedLayer.clearLayers();
}
if (tempMarker) {
tempMarker.remove();
}
}
2. Bus route query
Obtain the detailed information of a bus route according to the travel scheme obtained by transferSolutions.
//Click on a solution to get a specific route
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);
//Construct transferLines passed into iServer
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);
}
}
//Get detailed information about the bus route
function execTransPathQuery(id, transLines) {
//Set bus route parameters
var params = new SuperMap.TransferPathParameters({
points: paths["points"], //Starting point coordinates
transferLines: transLines //Current transfer route, including Route ID, starting and ending points, etc.
});
//Send the request to the server and handle the results returned from the server
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();
});
}
//Show the temporary stops and routes queried on the map
function setPopup() {
$(".busLink").click(function () {
tempRedLayer.clearLayers(); //Clear the temporary route layer
if (tempMarker) tempMarker.remove(); //Clear the temporary stop layer
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);
}
});
}
Run effects
Here only the route with least time cost will display. The query effect is as shown below:

Using Distributed Analysis Services
Distributed analysis services supported by SuperMap iClient for Leaflet include:
- Density Analysis
- Point Aggregation Analysis
- Single Object Query Analysis
- Region Summary Analysis
- Vector Clip Analysis
Sample: Density Analysis
Density analysis in distributed analysis services includes simple point density analysis and kernel density analysis.
- Simple point density analysis: Calculates the measure value per unit of the specified neighborhood area of a point. The value is calculated by dividing the sum of the measured values by the area of the specified neighborhood, and the density values will be added at the neighborhood superposition of the points. The density value of each output grid cell is the sum of density values of all the adjacent density values superimposed on the grid. The unit of the result grid is the reciprocal of the square of the original dataset unit. For example, if the original dataset unit is meter, then the result grid value unit is per square meter.
- Kernel density analysis: Calculates the point and line element measurement values within the specified neighborhood range. In a nutshell, it can directly reflect the distribution of discrete measurement values in the continuous region. The result is a smooth surface with small peripheral value and the grid value is the unit density, which is reduced to 0 at the neighborhood boundary. Kernel density analysis can be used to calculate population density, building density, crime report access, tourism area density monitoring, chain store operation analysis and so on.
Here we perform a simple point density analysis on registered big data, and the grid surface type is quadrilateral grid.
Set kernelDensityJobParams, including dataset, analysis method, analysis type, grid size, etc.
//Density analysis parameters
var kernelDensityJobParams = new SuperMap.KernelDensityJobParameter({
//Name of the registered dataset
datasetName: "newyork_taxi_2013_01_14k_csv_newyork_taxi_2013-01_14k",
//Grid size. For the quadrilateral, it is the grid length. For hexagonal meshes, it is the distance from the hexagonal vertex to the center point
resolution: 80,
//Analysis method, specify whether the analysis method is simple point density analysis, or kernel density analysis. 0 represents the former, and 1 represents the latter
method:0,
//Grid surface type, specify whether the grid unit is a quadrilateral grid or a hexagonal grid. 0 represents the former, and 1 represents the latter
meshType:0,
//Specifies the field index column number collection of the weight value of the points to be analyzed, and the field index starts at 0. The format is as follows: col7, col8
fields: col7,col8,
query: Bounds, //Analysis bounds
radius: 300, //The impact radius of the analysis
meshSizeUnit: Meter, //Grid size unit
radiusUnit: Meter, //Search radius unit
areaUnit: SquareMile, //Area unit
});
Submit the request for kernel analysis to the server, parse the results returned from the server, and display the results on the map.
//Initialize map
var map = L.map('map', {
crs: L.CRS.TianDiTu_WGS84,
center: [40.75, -73.95],
maxZoom: 18,
zoom: 12
}),
//Add Tianditu layer on the map
L.supermap.tiandituTileLayer("http://t{s}.tianditu.com/vec_c/wmts", {
layer: "vec",
tilematrixSet: "c"
}).addTo(map);
//Create distributed analysis service
var processingUrl ="http://localhost:8090/iserver/services/spatialprocessing/rest/v1/jobs";
var processingService = new L.supermap.processingService(processingUrl);
//Submit the request for kernel analysis to the server, parse the results returned from the server, and display the results on the map.
processingService.addKernelDensityJob(kernelDensityJobParams, function (serviceResult) {
//Pop a warning box and display error message for parsing failure
if (serviceResult.error) {
var errorMsg = serviceResult.error.errorMsg || "code: " + serviceResult.error.code;
showAlert("Create failure!
" + errorMsg, false);
return;
}
//Process the results and display the results on map if the analysis is successful
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);
});
}
});
});
Run effects

Sample: Point Aggregation Analysis
Point aggregation analysis refers to a spatial analysis operation for making aggregation maps for point datasets. divide the point elements of a map according to surface or polygons, and then calculate the number of points in each surface object, which will be regarded as the statistic value of the surface object. The weights of the points can also be introduced, and the weighted values of the interior points of the surface objects are considered as the statistic values of the surface objects. Based on the statistical values of the surface objects, the values will be sorted and the surface objects will be filled with color ramp.
Currently supported point aggregation analysis types include: grid surface aggregation and polygon aggregation, in which grid surface aggregation can be divided into quadrilateral grids and hexagonal grids.
Here we will implement a point aggregation analysis on the registered big data. The aggregation type is a grid surface aggregation, and the grid surface type is quadrilateral.
Set summaryMeshJobParam, including dataset, aggregation type, statistical mode, grid size, etc.
//Point aggregation analysis parameters
var summaryMeshJobParam = new SuperMap.SummaryMeshJobParameter({
//Name of the registered dataset
datasetName: "newyork_taxi_2013_01_14k_csv_newyork_taxi_2013-01_14k",
//Grid size. For the quadrilateral, it is the grid length. For hexagonal meshes, it is the distance from the hexagonal vertex to the center point
resolution: 80,
//Grid surface type, specify whether the grid unit is a quadrilateral grid or a hexagonal grid. 0 represents the former, and 1 represents the latter
meshType:0,
//Specifies the field index column number collection of the weight value of the points to be analyzed, and the field index starts at 0. The format is as follows: col7, col8
fields: col7,
query: Bounds, //Analysis bounds
statisticModes:,//Statistics mode, which needs to be consistent with the number of weight value fields
type:, SummaryType//Aggregation type, specifies whether the aggregation type is a grid surface aggregation or polygon aggregation.
//regionDataset: 'regionDataset', Aggregation surface dataset, used during polygon aggregation
});
Submit the request for point aggregation analysis to the server, parse the results returned from the server, and display the results on the map.
//Initialize map
var map = L.map('map', {
crs: L.CRS.TianDiTu_WGS84,
center: [40.75, -73.95],
maxZoom: 18,
zoom: 12
}),
//Add Tianditu layer on the map
L.supermap.tiandituTileLayer("http://t{s}.tianditu.com/vec_c/wmts", {
layer: "vec",
tilematrixSet: "c"
}).addTo(map);
//Create distributed analysis service
var processingUrl ="http://localhost:8090/iserver/services/spatialprocessing/rest/v1/jobs";
var processingService = new L.supermap.processingService(processingUrl);
//Submit the request for point aggregation analysis to the server, parse the results returned from the server, and display the results on the map.
processingService.addSummaryMeshJob(summaryMeshJobParam,function(serviceResult){
//Pop a warning box and display error message for parsing failure
if (serviceResult.error) {
var errorMsg = serviceResult.error.errorMsg || "code: " + serviceResult.error.code;
showAlert("Create failure!
" + errorMsg, false);
return;
}
//Process the results and display the results on map if the analysis is successful
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);
});
}
});
});
Run effects

Sample: Single Object Query Analysis
Spatial query is a query method that selects map features based on their spatial relationships to other feature. For example, if you want to know the number of five-star hotels within 5 km of Olympic venues in Beijing, you can first make a 5 km buffer of the Olympic venues; search the hotels within these buffers using the Containing query method; then, from the result hotels, find the hotels whose star level is 5 using attribute query and the final result can be obtained.
The single object spatial query refers to spatial query with only one query object. If there are multiple objects in the query object dataset, the object with the smallest SmID will serve as the query object.
Here we perform a single object query analysis on the registered big data, where the spatial query mode is intersect.
Set singleObjectQueryJobsParam, including source dataset, query object dataset, spatial query mode.
//Single object query analysis parameters
var singleObjectQueryJobsParam = new SuperMap.SingleObjectQueryJobsParameter({
datasetName: 'ProcessingData_processing_newyorkZone_R', //Name of the registered dataset
datasetQuery: 'ProcessingData_processing_singleRegion_R', //Name of the dataset where the query objects are
mode:SpatialQueryMode //Spatial query mode
});
Submit the request for single object query analysis to the server, parse the results returned from the server, and display the results on the map.
//Initialize map
var map = L.map('map', {
crs: L.CRS.TianDiTu_WGS84,
center: [40.75, -73.95],
maxZoom: 18,
zoom: 12
}),
//Add Tianditu layer on the map
L.supermap.tiandituTileLayer("http://t{s}.tianditu.com/vec_c/wmts", {
layer: "vec",
tilematrixSet: "c"
}).addTo(map);
//Create distributed analysis service
var processingUrl ="http://localhost:8090/iserver/services/spatialprocessing/rest/v1/jobs";
var processingService = new L.supermap.processingService(processingUrl);
//Submit the request for single object query analysis to the server, parse the results returned from the server, and display the results on the map.
processingService.addQueryJob(singleObjectQueryJobsParam,function(serviceResult){
//Pop a warning box and display error message for parsing failure
if (serviceResult.error) {
var errorMsg = serviceResult.error.errorMsg || "code: " + serviceResult.error.code;
showAlert("Create failure!
" + errorMsg, false);
return;
}
//Process the results and display the results on map if the analysis is successful
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);
});
}
});
});
Run effects

Sample: Region Summary Analysis
Region summary analysis refers to a spatial analysis for making aggregation maps for line and region datasets. The map lines and region features are divided according to grid surface or polygons, and then statistics will be done to the lines or regions in each grid cell according to standard attribute field or weight field. The statistical results will be regarded as the grid cell statistical values. Finally, the statistical values will be sorted and the grid cells will be rendered.
The concept of regional summary analysis is similar to that of point aggregation analysis. The difference is that point aggregation analysis does statistical calculation on point datasets, while the region summary analysis does statistical calculation for line and region datasets. For regional summary analysis, there are two statistical methods for the statistical values of grid cells: statistics based on standard attribute fields and weighted fields.
Here we perform a region summary analysis on the registered big data, where the region summary type is grid surface and the grid surface type is quadrilateral.
Set summaryRegionJobParam, including dataset, summary type, grid region summary type, etc.
//Region summary analysis parameters
var summaryRegionJobParam = new SuperMap.SummaryRegionJobParameter({
datasetName: 'ProcessingData_processing_newyorkZone_R', //Name of the registered dataset
//regionDataset: 'regionDataset', Aggregation region dataset, used during polygon aggregation
type: SummaryType, //Summary type, which can be grid surface summary and polygon summary
//Grid surface type, specify whether the grid unit is a quadrilateral grid or a hexagonal grid. 0 represents the former, and 1 represents the latter
meshType:0,
query: Bounds, //Analysis bounds
standardSummaryFields: true, //Whether to do statistics based on standard attribute field
//The statistical mode while doing statistics based on standard attribute field
standardStatisticModes: StatisticAnalystMode,
standardFields: "LocationID", //The field name when while doing statistics based on standard attribute field
weightedFields:false, //Whether to do statistics based on weight field
weightedStatisticModes: "", //The statistical mode while doing statistics based on weight field
weightedSummaryFields: "",//The field name while doing statistics based on weight field
//Grid size. For the quadrilateral, it is the grid length. For hexagonal meshes, it is the distance from the hexagonal vertex to the center point
resolution:100,
meshSizeUnit: Meter, //Grid size unit
sumShape:true //Whether to do statistics on length or area
});
2. Submit the request for region summary analysis to the server, parse the results returned from the server, and display the results on the map.
//Initialize map
var map = L.map('map', {
crs: L.CRS.TianDiTu_WGS84,
center: [40.75, -73.95],
maxZoom: 18,
zoom: 12
}),
//Add Tianditu layer on the map
L.supermap.tiandituTileLayer("http://t{s}.tianditu.com/vec_c/wmts", {
layer: "vec",
tilematrixSet: "c"
}).addTo(map);
//Create distributed analysis service
var processingUrl ="http://localhost:8090/iserver/services/spatialprocessing/rest/v1/jobs";
var processingService = new L.supermap.processingService(processingUrl);
//Submit the request for region summary analysis to the server, parse the results returned from the server, and display the results on the map.
processingService.addSummaryRegionJob(summaryRegionJobParam,
function(serviceResult){
//Pop a warning box and display error message for parsing failure
if (serviceResult.error) {
var errorMsg = serviceResult.error.errorMsg || "code: " + serviceResult.error.code;
showAlert("Create failure!
" + errorMsg, false);
return;
}
//Process the results and display the results on map if the analysis is successful
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);
});
}
});
});
Run effects

Sample: Vector Clip Analysis
Vector clip analysis is to clip the vector dataset, including internal clip and external clip. Internal clip maintains the portion within the clip area. External clip preserves the portion of dataset that is not within the clip area.
The vector clip analysis in distributed analysis service supports only one clip object. If there are multiple objects in the clip object dataset, the object with the smallest SmID will serve as the clip object.
Here we perform a vector clip analysis on the registered big data, employing the internal clip mode.
Set vectorClipJobsParam, including source data, clip object, clip object dataset, clip analysis mode.
//Vector clip analysis parameters
var vectorClipJobsParam = new SuperMap.VectorClipJobsParameter({
datasetName: 'ProcessingData_newyork_taxi_2013-01_14k', //Name of the registered dataset
datasetOverlay: 'ProcessingData_processing_singleRegion_R',//Name of the dataset where the clip object is
mode:ClipAnalystMode //Clip analysis mode
});
Submit the request for vector clip analysis to the server, parse the results returned from the server, and display the results on the map.
//Initialize map
var map = L.map('map', {
crs: L.CRS.TianDiTu_WGS84,
center: [40.75, -73.95],
maxZoom: 18,
zoom: 12
}),
//Add Tianditu layer on the map
L.supermap.tiandituTileLayer("http://t{s}.tianditu.com/vec_c/wmts", {
layer: "vec",
tilematrixSet: "c"
}).addTo(map);
//Create distributed analysis service
var processingUrl ="http://localhost:8090/iserver/services/spatialprocessing/rest/v1/jobs";
var processingService = new L.supermap.processingService(processingUrl);
//Submit the request for vector clip analysis to the server, parse the results returned from the server, and display the results on the map.
processingService.addVectorClipJob(vectorClipJobsParam, function(serviceResult){
//Pop a warning box and display error message for parsing failure
if (serviceResult.error) {
var errorMsg = serviceResult.error.errorMsg || "code: " + serviceResult.error.code;
showAlert("Create failure!
" + errorMsg, false);
return;
}
//Process the results and display the results on map if the analysis is successful
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);
});
}
});
});
Run effects

Using Data Stream Services
//Create real time data layer
var urlDataFlow = "ws://localhost:8091/iserver/services/dataflow/dataflow";
var dataFlowLayer = L.supermap.dataFlowLayer(urlDataFlow, {
//Optional, elements within the GeoJSON filter will be returned
geometry:{coordinates:[[[116.38,39.87],[116.41,39.87],[116.41,39.84],[116.38, 39.84],[116.38,39.87]]],type:"Polygon"},
//Optional, return excluded fields
excludeField:["id"],
//Optional, return feature coordinate system
prjCoordSys:4326
});
dataFlowLayer.addTo(map);
The following graph shows the effects of real-time data at different times, and you can see that the data is displayed in different locations.
Run effects


Using Address Matching Services
SuperMap iClient for Leaflet supports address matching service, which includes forward address matching and reverse address matching. Users can find the location using address, and they can also get the address of a location on the map.
Here we introduce how to perform address matching using China_4326.
Sample: Forward Address Matching
Forward address matching obtains geographic coordinates and structured and detailed address description based on address description, city bounds.
//Initialize map
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);
//Forward matching parameters
var geoCodeParam = new SuperMap.GeoCodingParameter({
address: "SuperMap", //Address
fromIndex:0, //Min index
toIndex:10, //Max index
filters: "Company", //Filter condition
prjCoordSys:{epsgcode26}, //Set coordinates
maxReturn:3 //Max results
});
//Createm address matching service
var addressUrl = "https://iserver.supermap.io/iserver/services/addressmatch-Address/restjsr/v1/address",
var addressMatchService = L.supermap.addressMatchService(addressUrl);
//Send request to the server to operate forward address matching. The server will return the results and the results will be handled
addressMatchService.code(geoCodeParam, match);
//Handle the results and display the results on the map and add pop up window
function match(obj) {
obj.result.map(function (item) {
var marker = L.marker([item.location.y, item.location.x]);
decodeMarkers.push(marker);
var innerHTML = "";
innerHTML += "Address:" + 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 += "Coordinates:[" + x + "," + y + "]<br>";
if (item.score > 0) {
innerHTML += "Matching rate:" + item.score + "<br>";
}
innerHTML += "Filter field:" + 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);//Set map display bounds
}
Run effects

Sample: Reverse Address Matching
Get the corresponding address description according to reverse address matching based on input address coordinates
//Initialize map
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);
//Reverse matching parameters
var geoDecodeParam = new SuperMap.GeoDecodingParameter({
x:116.3518541194, //X coordinate
y:40.00097839595, //Y coordinate
fromIndex:0, //Min index
toIndex:10, //Max index
filters: "", //Filter field
prjCoordSys:{epsgcode26}, //Set coordinates
maxReturn:3, //Max results
geoDecodingRadius:1000 //Search radius
});
//Create address matching service
var addressUrl = "https://iserver.supermap.io/iserver/services/addressmatch-Address/restjsr/v1/address",
var addressMatchService = L.supermap.addressMatchService(addressUrl);
//Send request to the server to operate forward address matching. The server will return the results and the results will be handled
addressMatchService.decode(geoDecodeParam, match);
//Handle the results and display the results on the map and add pop up window
function match(obj) {
obj.result.map(function (item) {
var marker = L.marker([item.location.y, item.location.x]);
decodeMarkers.push(marker);
var innerHTML = "";
innerHTML += "Addresss:" + 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 += "Coordinates:[" + x + "," + y + "]<br>";
if (item.score > 0) {
innerHTML += "Matching rate:" + item.score + "<br>";
}
innerHTML += "Filter field:" + 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);//Set map display bounds
}
Run effects
