拓扑线图层介绍
本节内容
拓扑线层介绍
TopoLineLayer是从DynamicLayer派生出来的有拓扑关系的动态线图层。利用拓扑图层的特性可以创建各类应用。由于拓扑图层中的实体相互之间存在拓扑关系,所以很容易的进行类似电路线路、道路管线等图形项目的开发。
拓扑图层中的实体类型
拓扑层中包含三种实体类型,分别是点实体、线实体和组实体。由于是拓扑层,所以它们之间存在着拓扑关系,如点实体记录连接的所有线,线实体记录起始点,组实体记录所有子实体,子实体记录父实体。这里要注意的是,目前只支持一层递归关系,即组实体不能在作为子实体,子实体必须是线实体。三类实体保存在图层对象的不同数组中,起始的oid都为0。
创建带有拓扑关系的实体对象
下面通过一些简单的例子来分部介绍拓扑线层的使用,并且后面还要基于这个例子做一些更深入的行业应用专题。
1. 添加点实体对象
在拓扑线层中添加点实体很简单,首先要得到地图中心位置的经纬度,然后调用addPointObject()方法将经纬度传入即可。
代码如下:
//得到classFactory对象,用它来创建各种不同类型的对象
var oClassFactory = oMapViewer.classFactory;
//得到屏幕中央点经度
var centerX = oMapViewer.renderContext.coordSystem.centerPoint.x;
//得到屏幕中央点纬度
var centerY = oMapViewer.renderContext.coordSystem.centerPoint.y;
//在地图上创建一个名为"NewTopoLineLayer"的拓扑层
var topoLayer = oMapViewer.topoLineLayers.addlayer("NewTopoLineLayer");
//创建一个图例对象
var pointRed = oClassFactory.createLegend();
//将图例设置成红色
pointRed.initSimplePoint(1, oClassFactory.createColor(255, 0, 0), true);
//通过拓扑层对象的addPointObject()方法向地图上添加点实体
var pointObj = topoLayer.addPointObject(centerX, centerY);
//设置点实体的标注
pointObj.text = "一个点实体";
//将点实体的颜色设置为红色
pointObj.legend = pointRed;
//重画地图
oMapViewer.redraw();
通过上述代码就可以向地图中添加一个点实体。创建点实体操作可以总结为:创建拓扑图层、得到屏幕坐标、添加点、设置点属性这四步来完成。
2. 添加线实体对象
由于线实体记录的是起始和结束的点。所以添加线实体的前提是添加两个点实体,然后以这两个点实体为首尾添加线实体。
详细的代码讲解如下:
var centerX = oMapViewer.renderContext.coordSystem.centerPoint.x;
var centerY = oMapViewer.renderContext.coordSystem.centerPoint.y;
var Layer_Name="NewTopoLinelayer";
var topoLayer;
var factory = oMapViewer.classFactory;
var pointRed,pointGreen,pointBlue;
var lineGreen;
//创建四个图例并设置不同的颜色
function createLegends()
{
pointRed=factory.createLegend();
pointRed.initSimplePoint(1,factory.createColor(196,0,128),true);
pointGreen=factory.createLegend();
pointGreen.initSimplePoint(1,factory.createColor(0,255,0),true);
pointBlue=factory.createLegend();
pointBlue.initSimplePoint(1,factory.createColor(0,0,255),true);
lineGreen=factory.createLegend();
lineGreen.initSimpleLine(1,factory.createColor(0,128,0));
}
//添加点
function addPoints()
{
addOnePoint('拓扑点一',centerX,centerY,pointRed);
addOnePoint('拓扑点二',centerX+1.5,centerY,pointGreen);
}
//向地图中添加点
function addOnePoint(pointName,x,y,legend)
{
var pointObject=topoLayer.addPointObject(x,y);
pointObject.text=pointName;
pointObject.legend=legend;
//将点实体的oid号存放到数组中
nameMapping[pointName]=pointObject.oid;
}
//添加线,并按照指定的路径设置线的名称
function addLineGroup(groupString,legend)
{
var pointNames=groupString.split(' ');
if(pointNames.length<=0)
return;
var name1,name2;
var startName, endName;
var lineName;
var groupName;
startName=pointNames[0];
endName=pointNames[pointNames.length-1];
groupName = startName + '-' + endName;
var objs=factory.createNumberArray();
var lineIndex;
for(var i=0; i<pointNames.length-1;i++)
{
name1=pointNames[i];
name2=pointNames[i+1];
lineName=name1+'-'+name2;
lineIndex=addOneLine(name1,name2,lineName,groupName,legend);
if(lineIndex>=0)
objs.add(lineIndex);
}
var groupObject=topoLayer.addLineGroupObject(objs);
}
//向地图中添加线
function addOneLine(startPointName,endPointName,lineName,groupName,legend)
{
var indexStart;
var indexEnd;
indexStart=nameMapping[startPointName];
indexEnd=nameMapping[endPointName];
if(indexStart==null || indexEnd==null)
return -1;
var lineObject=topoLayer.addLineObject(indexStart,indexEnd);
lineObject.legend = legend;
lineObject.attr = lineName;
lineObject.text = "拓扑线";
return lineObject.oid;
}
//调用相关方法在地图上添加点和线
function createTopoLayer()
{
createLegends();
topoLayer=oMapViewer.topoLineLayers.addLayer(Layer_Name);
nameMapping=new Object();
addPoints();
//添加线
addLineGroup("拓扑线一 拓扑线二",lineGreen);
topoLayer.enableParaDrawing=true;
topoLayer.paraLenFromLine=12;
topoLayer.paraLenAlongLine=10;
topoLayer.paraLenBase=20;
oMapViewer.isSelectGroup=true;
topoLayer.markDuplicateLines();
oMapViewer.redraw();
}
createTopoLayer();
执行上述代码便在地图上创建了一条连接两个点的线,并且线的名称为两个点名称的组合。添加线操作最重要的地方就是分割线经过的路径名称,然后照此设置线的属性和线组的类型。
综合应用 -- 电信干路图
看过上述添加点和添加线的方法介绍后,就可以创建更为复杂的应用了。比如创建一个多城市之间的电信线路图就可以使用上面介绍的方法。使用点实体来代替各个城市,使用线实体连接各个实体点,这样便构成了一副电信干路图,并且我们可以添加更多的功能使其可以实现图文互查。
创建电信干路图这个例子里,可以使用上面介绍的添加点和线的方法,将添加的点换成各个城市的真实坐标。添加线的时候可以设置线经过的路径节点的名称。这样就可以创建一条经过不同实体点的线了。
例如添加点的时候可以按照各个城市的真实坐标添加:
addOnePoint('北京',116.16,40.0,pointRed);
addOnePoint('天津',117.0,39.3,pointGreen);
addOnePoint('石家庄',114.3,38.2,pointBlue);
addOnePoint('济南',116.8,36.8,pointGreen);
addOnePoint('郑州',113.5,34.9,pointGreen);
addOnePoint('武汉',114.1,30.7,pointRed);
addOnePoint('长沙',112.8,28.35,pointBlue);
addOnePoint('广州',113.0,23.25,pointRed);
addOnePoint('西安',108.75,34.6,pointGreen);
添加线路,并设置线路经过的路径
addLineGroup('北京 天津',lineBlue); //添加一条连接北京和天津的线
addLineGroup('天津 济南',lineBlue);
addLineGroup('北京 石家庄 济南',lineGreen); //添加一条北京到济南途径石家庄的线
addLineGroup('北京 石家庄 郑州 武汉 长沙 广州',lineRed);
按照如上步骤便创建了一副多个城市之间的电信线路图,每个城市之间都有多条线路通过。当然上面所介绍的只是一些最基本的功能,下面介绍一些高级功能,可以实现图文互查等高级操作。
查看实体信息
拓扑线层上的各种实体都是有属性的。这些属性可以通过添加选择实体事件的方法进行显示。selObject(Layer_Name, oid)方法实现了显示实体属性信息的功能,它返回所选择实体所在的图层名和其oid号。另外还需要使用oMapViewer类的setCurrentTool(4)方法将地图设置为选择状态。
例如,如下代码便添加了一个选择事件,当用鼠标点击点实体或线实体时显示其属性。
<script language="JavaScript" for="oMapViewer" event="selObject(layerName,oid)">
var sResult;
var layer=oMapViewer.topoLineLayers.getLayerByName(layerName);
if(layer!=null && layer.getFocusObjectCount()>0)
{
var ob=layer.getFocusObject(0);
var msg;
if(ob!=null)
{
if(ob.subObjects!=null)
msg="组实体 : "+ob.text;
else
{
if(ob.spaType==1) //当选择的为点实体时
msg="站点实体 : "+ob.text;
else //当选择的为线实体时
msg="子段实体 : "+ob.attr + " 隶属于: " + ob.text;
}
msg= msg+ ": linecount: " + ob.lines.getSize();
sResult = layerName + ":" + msg;
window.status = "sResult";
}
}
</script>
组实体模式
在创建电信干路图的例子中,电信干路也就是线实体的创建需要设置其首尾两点,和途径的每个点。也就是说一条连接两个城市的电信干路可以被途径的各个点划分为多个段。因此在查看线路信息的时候可以查看整条线路的信息也可以只查看其中一段线路的信息。要设置查看的类型是否采用组实体模式可以通过设置oMapViewer类的isSelectGroup属性来实现,当设置为true是表示采用组实体模式。
代码如下:
function setGroupModel()
{
oMapViewer.isSelectGroup = true; //使用组实体模式
//oMapViewer.isSelectGroup = false; //不使用组实体模式
}
设置拓扑线层的显示
可以对拓扑线层进行设置来改变其显示模式。例如上面创建的电信干路图的例子中,当地图拉远时两个城市之间的多条线路只显示为一条直线,当地图拉近后两点间的多条线路便自动分开,避免线路的重叠显示。要设置重线避让需要得到拓扑线层对象,然后设置其enableParaDrawing属性。当设置为true时当地图缩放的一定大小时,多条线路便自动分开显示,当设置为false时则多条线路只绘制成一条。注意:当线在视觉上过短时,即使enableParaDrawing = true,系统也自动只画一条线。
代码如下:
function setParaDraw()
{
var layer = oMapViewer.topoLineLayers.getLayerByName(Layer_Name);
layer.enableParaDrawing = true; //使用重现避让
}
设置避让线的显示模式
多条线路之间进行避让显示时,可以设置避让显示的样式。系统提供了三个参数进行控制,它们都有默认值,也可以自己重新进行设定。paraLenBase: 从端点到线起始分开点的沿线长度,默认取值15。paraLenAlogLine:从线起始分开点到线平行点的沿线长度,默认取值15。paraLenFromLine:平行线之间的距离,默认取值8。
效果如下:

紧凑模式显示线路名称
拓扑图层的compactAnno属性可以设置线路名称的显示样式,当设置为true时,使用紧凑的样式显示线路名称,设置false时则为普通显示。同设置重线避让相同首先也要得到拓扑线层的对象。
代码如下:
function setCompactAnno()
{
var layer = oMapViewer.topoLineLayers.getLayerByName(Layer_Name);
layer.compactAnno = true;
}
移动点实体
在地图上创建实体完成后,能够对其进行修改,可以通过拖拽的方式改变点实体的位置,同时连接各个点实体的线实体也会随着进行移动。要实现移动点实体的功能需要使用oMapViewer类的setMovePointOperation()方法,它接受一个图层名作为参数。
代码如下:
function movePoint()
{
//参数为图层名称
oMapViewer.setMovePointOperation(Layer_Name);
}
查看站点移动历史
当移动点实体时,其isModefied属性便会设置为true。表示已经被修改了。所以要查看移动了那些点实体,可以通过遍历所有点实体并判断isModefied属性的方法来实现。
function checkModify()
{
var layer = oMapViewer.topoLineLayers.getLayerByName(Layer_Name);
var sHistory = "移动实体历史记录: " + "\n";
if(layer == null)
return;
var pointObj;
for(var i=0; i<layer.getPointObjectCount(); i++)
{
pointObj = layer.getPointObject(i);
if(pointObj == null);
continue;
if(pointObj.isModefied)
sHistory += '实体id:' + pointObj.oid + ' 实体名称: ' + pointObj.text + '\n';
pointObj.isModefied = false;
}
alert(sHistory);
}
在上面的代码中,通过getPointObjectCount()方法得到了实体的总数。通过getPointObject()方法得到指定索引的点实体对象。
保存地图显示为图片
在地图上进行相关的编辑后,可以通过jpg图片的方式将其保存。保存图片需要使用oMapViewer类的saveAdJpeg()方法实现,它接受两个参数,一个是保存的文件名,另一个是文件保存的质量。
代码如下:
function savePic()
{
oMapViewer.saveAdJpeg("d:\pic1.jpg", 80);
alert("已经保存到d:\\pic1.jpg");
}