《慢性病地理信息系统——“路径查询”模块》项目研发阶段性总结-------------拓扑交通路线图与最佳路径分析
《慢性病地理信息系统——“路径查询”模块》项目研发阶段性总结
··························································
开发工具:Visual Studio 2015
关键技术:SuperMap iDesktop 9D、C#MVC
作者:邵亮华
完成模块功能:路经查询
撰写时间:2019-01-17
··························································
拓扑交通路线图与最佳路径分析
我在做GIS项目时,其中有个最佳路径分析的功能。当我调试项目里最佳路径分析的功能时,它老报一个错误,如图:
这个原因是我发布的交通服务的url不正确,所以在使用交通服务的url查询时报错。
这个最佳路径分析需要在拓扑构网构建一个二维网络(二维的交通路线)
一、打开SuperMap iDesktop 9D
1、先需要构建二维交通路线图
2、接下来会弹出一个构建二维网络数据集的窗体,点击文件夹的图标,添加想要拓扑的对象
3、由于构建二维的交通路线会有相交、重复等等错误数据的产生,会影响后续的数据处理和工作分析、影响数据的质量和可用性,SuperMap iDesktop 9D的打断容限,就能完美解决这个问题。
- 打断容限值:单位与数据集的单位相同。用于控制线数据集打断时的节点选择。若两条线段的交点与点数据集中邻近点的距离在此容限范围内,则予以打断;否则不进行打断处理。
- 节点容限:单位与数据集的单位相同。Fuzzy 容限即是图层的精度(分辨率),代表顶点(Vertex)或结点(Node)之间的最小距离。也就是说,在此距离之内的两个点可以视为重合。Fuzzy 容限一般为图层范围的1/10000 -- 1/1000000之间。为确保地图精度,本系统默认为1/1000000。
(往里面多添加几个零,将打断容限值最小化)
4、确认之后会它会自动生成一个数据集
5、打开刚刚新构建的数据集CasePath,点击交通分析下方的最佳路径分析调试一下是否执行成功,没有问题就将数据集CasePath拉到地图里即可。
二、打开SuperMap iserver发布地图(或者直接在SuperMap iDesktop 9D发布)
1、在SuperMap iserver发布地图
2、记住重要字段
3、分布地图后,打开SuperMap iserver的工作空间
4、找到该地图的交通网络分析服务
5、跳转到该服务地址,点击到下一级
6、再下一级
7、再再下一级
8、最后跳转到网络数据名的界面才是正确的网络交通路线url
三、项目执行
最佳路径查询的功能是我从数据库查询出数据再引用SuperMap iserver的最佳路径分析案例完成的功能,如图:
首先输入条件查询出该病人信息,点击病人弹出病人信息框,再点击《活动路径》按钮,在地图图层显示出路径坐标,再点击《查询》进行最佳路径分析
经典代码:
1、需要获取地图的url与网络交通分析的url
2、声明地图map、图层layer的变量和两种不同的图层控件,再为图层layer使用on()接口监听事件,方便添加图层控件
3、添加图层控件
JS部分
function SelectPath() {
var SeRecordNum = $("#SeRecordNum").val();
var PathDate1 = $("#PathDate1").val();
var PathDate2 = $("#PathDate2").val();
if (SeRecordNum != null ) {
if (PathDate1 != null && PathDate2 != null) {
var form = $("#SelectPath").serializeArray();
$.post("/Main/SelectCase", form, function (data) { //数组查询、提交只能用post提交
if (data.length > 0) {
var marker = null;
var bool = true;
//初始化弹窗参数---------------------------------------------------
var size = new SuperMap.Size(25, 20);//标记的大小
var offset = new SuperMap.Pixel(-(size.w / 2), -size.h);//此类用x,y坐标描绘屏幕坐标(像素点)。
var icon = new SuperMap.Icon('/Content/layui-v2.3.0/layui-v2.3.0/layui/images/face/1.gif', size, offset);//图标类,表示显示在屏幕上的图标
//---------------------------------------------------
for (var i = 0; i < data.length; i++) {
//初始化标记覆盖物类
marker = new SuperMap.Marker(new SuperMap.LonLat(data[i].SiteCoordinateX, data[i].SiteCoordinateY), icon);//LonLat坐标
marker.CaseRecordID = data[i].CaseRecordID;
marker.CasePeopleID = data[i].CasePeopleID;
marker.SiteCoordinateX = data[i].SiteCoordinateX;
marker.SiteCoordinateY = data[i].SiteCoordinateY;
marker.CaseMC = data[i].CaseMC;
marker.RecordNum = data[i].RecordNum;
marker.RecordDate = data[i].RecordDate;
marker.CaseType = data[i].CaseType;
marker.CasePeopleMC = data[i].CasePeopleMC;
marker.Site = data[i].Site;
marker.Age = data[i].Age;
marker.Native = data[i].Native;
marker.Sex = data[i].Sex;
//注册 click 事件,触发 mouseClickHandler()方法
marker.events.on({
'click': Openfr,//单击触发
'touchstart': Openfr,//当在触摸屏上对marker开始进行触摸时触发此事件。//假如要在移动端的浏览器也实现点击弹框,则在注册touch类事件
"scope": marker,//大概是传参数把
});
markerLayer.addMarker(marker);//添加到图层
}
} else {
alert("没有查询出数据");
}
})
}
else {
alert("请输入日期");
}
}
else {
alert("请输入登记号");
}
}
//病例的活动路径查询坐标事件
function SelectCasePath(CasePeopleID) {
var PathDate1 = $("#PathDate1").val();
var PathDate2 = $("#PathDate2").val();
var temp = "";
if (PathDate1 > PathDate2) {
temp = PathDate2;
PathDate2 = PathDate1;
PathDate1 = temp;
}
$.post("/Main/SelectCasePath", { CasePeopleID: CasePeopleID, PathDate1: PathDate1, PathDate2: PathDate2 }, function (data) {
if (data.length > 0) {
var marker = null;
var bool = true;
//初始化弹窗参数---------------------------------------------------
var size = new SuperMap.Size(25, 20);//标记的大小
var offset = new SuperMap.Pixel(-(size.w / 2), -size.h);//此类用x,y坐标描绘屏幕坐标(像素点)。
//图标类,表示显示在屏幕上的图标
var icon = new SuperMap.Icon('/Content/layui-v2.3.0/layui-v2.3.0/layui/images/face/4.gif', size, offset);
//---------------------------------------------------
for (var i = 0; i < data.length; i++) {
var X = data[i].PathX;
var Y = data[i].PathY;
//初始化标记覆盖物类
marker = new SuperMap.Marker(new SuperMap.LonLat(X,Y), icon);//LonLat坐标
markerLayer.addMarker(marker);//添加到图层
var point = new SuperMap.Geometry.Point(X, Y);
//获取点的坐标与 ID 的数组
nodeArray.push(point);
}
} else {
alert("没有查询出数据");
}
})
}
var nodeArray = [], pathTime, pathListIndex = 0, routeCompsIndex = 0;
// 病例的活动最佳分析路径查询
function findPath() {
var findPathService, parameter, analystParameter, resultSetting;
resultSetting = new SuperMap.REST.TransportationAnalystResultSetting({
returnEdgeFeatures: true,
returnEdgeGeometry: true,
returnEdgeIDs: true,
returnNodeFeatures: true,
returnNodeGeometry: true,
returnNodeIDs: true,
returnPathGuides: true,
returnRoutes: true
});
analystParameter = new SuperMap.REST.TransportationAnalystParameter({
resultSetting: resultSetting,
weightFieldName: "SmLength"
//weightFieldName:阻力字段的名称,标识了进行网络分析时所使用的阻力字段,例如表示时间、长度等的字段都可以用作阻力字段。 该字段默值为服务器发布的所有耗费字段的第一个字段。
});
parameter = new SuperMap.REST.FindPathParameters({
isAnalyzeById: false,
//isAnalyzeById:事件点和设施点是否通过节点 ID 号来指定,默认为 false,即通过坐标点指定事件点和设施点。
nodes: nodeArray, //nodes:应为点的坐标与 ID 的数组
hasLeastEdgeCount: false, //hasLeastEdgeCount:是否按照弧段数最少的进行最佳路径分析
parameter: analystParameter
});
if (nodeArray.length <= 1) {
alert("站点数目有误");
}
findPathService = new SuperMap.REST.FindPathService(url2, {
eventListeners: { "processCompleted": processPathCompleted }
});
findPathService.processAsync(parameter);
}
// 病例的活动最佳分析路径查询结果
function processPathCompleted(findPathEventArgs) {
var result = findPathEventArgs.result;
if (pathListIndex < result.pathList.length) {
addPath(result);
} else {
pathListIndex = 0;
//线绘制完成后会绘制关于路径指引点的信息
addPathGuideItems(result);
}
}
//以动画效果显示分析结果
function addPath(result) {
if (routeCompsIndex < result.pathList[pathListIndex].route.components.length) {
var pathFeature = new SuperMap.Feature.Vector();
var points = [];
for (var k = 0; k < 2; k++) {
if (result.pathList[pathListIndex].route.components[routeCompsIndex + k]) {
points.push(new SuperMap.Geometry.Point(result.pathList[pathListIndex].route.components[routeCompsIndex + k].x, result.pathList[pathListIndex].route.components[routeCompsIndex + k].y));
}
}
var curLine = new SuperMap.Geometry.LinearRing(points);
pathFeature.geometry = curLine;
pathFeature.style = style;
lineLayer.addFeatures(pathFeature);
//每隔0.001毫秒加载一条弧段
pathTime = setTimeout(function () { addPath(result); }, 0.001);
routeCompsIndex++;
} else {
clearTimeout(pathTime);
routeCompsIndex = 0;
pathListIndex++;
allScheme(result);
}
}
//在路线上添加人型的图片
function addPathGuideItems(result) {
lineLayer.removeAllFeatures();
//显示每个pathGuideItem和对应的描述信息
for (var k = 0; k < result.pathList.length; k++) {
var pathGuideItems = result.pathList[pathListIndex].pathGuideItems, len = pathGuideItems.length;
for (var m = 0; m < len; m++) {
var guideFeature = new SuperMap.Feature.Vector();
guideFeature.geometry = pathGuideItems[m].geometry;
guideFeature.attributes = { description: pathGuideItems[m].description };
if (guideFeature.geometry.CLASS_NAME === "SuperMap.Geometry.Point") {
guideFeature.style = styleGuidePoint;
}
else {
guideFeature.style = style;
}
lineLayer.addFeatures(guideFeature);
}
}
}
4、相关业务表和关系
四、开发总结
我刚刚上手对于SuperMap iDesktop 9D的运用不是熟。一路摸索,从开始绘制二维地图然后到发布,这个复杂的过程让人有点烦躁,特别是里面的图层显示还有颜色的一系列的规划,密密麻麻的让人有点晕头,不过做出来倒是蛮有成就感的(虽然比百度地图、谷歌地图差了点)。
我在做在做这个GIS的项目最佳路径分析得到几个心得
一、在做这个交通路线的拓扑图时,一定要注意构建二维网络数据集的窗体里的打断容限(往里面多添加几个零,将打断容限值最小化)
由于构建二维的交通路线会有相交、重复等等错误数据的产生,会影响后续的数据处理和工作分析、影响数据的质量和可用性,SuperMap iDesktop 9D的打断容限,就能完美解决这个问题。
二、GIS的项目最佳路径分析:
1、要理清地图与图层的关系,想要在地图上显示想要的样式必须要在地图上加图层,我项目用了两种类型的图层控件一种是SuperMap.Layer.Markers用来创建有标签的图层,另一种是SuperMap.Layer.Vector用来矢量图层。
2、要理清地图url与与交通网络图的url,获取地图的url可以得到地图的数据,然后借助拓扑的交通网络图的url分析交通路线。