查询ArcIMS中的动态图层(引自ESRI北京论坛)
为了解决客户的问题, 捣鼓了一下arcims的动态图层,因为前后花了我十来个小时,所以还是想写下来和大家分享,有不同意见欢迎广泛交流.
一.关于添加动态图层
这是个很不值得一提的问题,看到这个标题,估计很多老师和资深人士都想扔砖头过来.大家还是耐心点儿,古典长篇名著还要从滚滚长江东逝水开始呢.我们也先弄个引子,顺便充实一下篇幅.
1.修改AXL文件
添加动态图层有个前提,就是必须在AXL中,为MAP元素,添加dynamic属性,即:
<MAP dynamic="true">
这个步骤在Author中无法完成,只能通过文本编辑器手工编辑了.建议使用EmEditor或者VS.
2.动态添加
通过发送ArcXML或者调用连接器中封装的对象,我们就可以动态添加指定的图层,下面是使用ArcIMS Java Connector的例子:
(1)动态添加SHAPE图层
.....
ShapeWorkspace shpw = new ShapeWorkspace();
shpw.setDirectory("D:\\WorkSpace\\sd");
shpw.setName("sde_ws-1");
map.addWorkspace(shpw);
Dataset data = new Dataset();
data.setName("地区边界");
data.setWorkspaceName(shpw.getName());
data.setType("polygon");
FeatureLayer fl = new FeatureLayer("2", null, null);
fl.setDataset(data);
fl.setName("地区边界");
fl.setVisible(true);
SimpleRenderer sr = new SimpleRenderer();
SimplePolygonSymbol sm=new SimplePolygonSymbol();
sm.setFillColor("255,0,0");
sm.setBoundaryColor("0,0,255");
sm.setFillType(SimplePolygonSymbol.SOLID);
sr.setSymbol(sm);
fl.setRenderer(sr);
map.getLayers().add(fl);
(2)SDE图层
......
SDEWorkspace sdeWSP = new SDEWorkspace();
sdeWSP.setName("sde_ws-4");
sdeWSP.setInstance("port:5151");
sdeWSP.setServer("jerry");
sdeWSP.setPassword("sde");
sdeWSP.setUser("sde");
map.addWorkspace(sdeWSP);
Dataset data = new Dataset();
data.setName("SDE.地区边界");
data.setWorkspaceName(sdeWSP.getName());
data.setType("polygon");
FeatureLayer fl = new FeatureLayer("2", null, null);
fl.setDataset(data);
fl.setName("地区边界");
fl.setVisible(true);
SimpleRenderer sr = new SimpleRenderer();
SimplePolygonSymbol sm=new SimplePolygonSymbol();
sm.setFillColor("255,0,0");
sm.setBoundaryColor("0,0,255");
sm.setFillType(SimplePolygonSymbol.SOLID);
sr.setSymbol(sm);
fl.setRenderer(sr);
map.getLayers().add(fl);
二.动态图层的查询
1.还是从修改AXL文件开始
如果要使添加的动态图层可以被查询,比如Identify, 缓冲区查询等等,必须具备一个前提,必须在AXL中,为MAP元素,添加dynamicfeature="true">属性,即:
<MAP dynamic="true" dynamicfeature="true">
2.两个注意事项
经过反复测试,发现必须注意两点:
(1)执行查询时,必须添加对于LAYER的DATASET的定义.而且,DATASET的workspace属性必须是已经包含在AXL文件中.
(2)如果不是直接发送ArcXML,那么查询之前需要Remove掉动态添加上去的所有workspace
3.执行查询的例子
查询的应用类型很多,包括点击地图的Identify,还有图上的框选,圈选,多边形选择,甚至缓冲区查询等等. 有时候还需要结合属性where条件的筛选.对于ArcIMS而言,都是
SPATIALQUERY. 下面就以Identify的点击查询为例.
(1)直接发送ArcXML:
<?xml version="1.0" encoding="UTF-8"?><ARCXML version="1.1">
<ARCXML>
<REQUEST>
<GET_FEATURES envelope="true" geometry="true" outputmode="newxml">
<LAYER id="2" type="featureclass">
<DATASET name="SDE.地区边界" type="polygon" workspace="sde_ws-4" />
</LAYER>
<SPATIALQUERY searchorder="optimize" subfields="DIST_CODE NAME #SHAPE#">
<SPATIALFILTER relation="area_intersection">
<ENVELOPE maxx="120.9610390189751" maxy="37.32400679575094" minx="120.9608390189751" miny="37.32380679575093"/>
</SPATIALFILTER>
</SPATIALQUERY>
</GET_FEATURES>
</REQUEST>
</ARCXML>
注意在LAYER的元素中添加的DATASET的定义.其中,DATASET的workspace属性必须是已经包含在AXL文件的WORKSPACE中.什么
意思呢?就拿这个例子中而言,其中的"sde_ws-4"必须是在这个地图服务的AXL文件中定义过的SDEWORKSPACE.
(2)使用Java Connector程序进行查询:
......
//注意在这里需要获取当前map中的workspace,赋给一个临时变量,然后从map中去除
SDEWorkspace sdeWSP = new SDEWorkspace();
sdeWSP=(SDEWorkspace)map.getWorkspace(0);
map.removeWorkspace(0);
FeatureLayer fLayer=(FeatureLayer)map.getLayers().item(0);
//注意在这里必须声明Dataset,并且赋予相应的Name, workspace,type等属性,其中workspace名称很重要,必须也是定义在AXL中.
//然后把Dataset对象赋给FeatureLayer对象
Dataset data = new Dataset();
data.setName("SDE.地区边界");
data.setWorkspaceName("sde_ws-4");
data.setType("polygon");
fLayer.setDataset(data);
com.esri.aims.mtier.model.map.layer.query.Filter filter= new com.esri.aims.mtier.model.map.layer.query.Filter();
Point pnt = map.toMapPoint(Double.parseDouble(x), Double.parseDouble(y));
double maxx = pnt.getX() + 0.0001;
double maxy = pnt.getY() + 0.0001;
double minx = pnt.getX() - 0.0001;
double miny = pnt.getY() - 0.0001;
Envelope envelope = new Envelope();
envelope.setMinX(minx);
envelope.setMinY(miny);
envelope.setMaxX(maxx);
envelope.setMaxY(maxy);
filter.setSpatialShape(envelope);
filter.setGlobalEnvelope(true);
filter.setBoundingEnvelope(true);
filter.addSubField("DIST_CODE");
filter.addSubField("NAME");
filter.setRelation(com.esri.aims.mtier.model.map.layer.query.Filter.AREA_INTERSECTION);
fLayer.getRecordset().clearRecordset();
fLayer.setFilterObject(filter);
map.refresh();
//执行完查询之后,如果有必要,将之前去除的workspace添加到map中.
map.addWorkspace(sdeWSP);
......
4.常见错误信息
(1) Underlying input stream returned zero bytes
表明没有指定Layer的Dataset,或者Dataset中的workspace没有定义在AXL文件中.
对于仅仅添加动态图层而言,workspace的名字可以是任意的,而且可以不用定义在AXL文件中.但是如果涉及到对于动态图层的查询,就必须注意这一点.
(2) map.refresh()时候,提交到后台的请求是GET_IMAGE而不是想要执行的GET_FEATURE
这个问题的原因是因为没有在查询之前去除map中包含的workspace
(3) 添加了动态图层以后,无法查询其他固有的图层
这个问题的原因同2,也是因为没有在查询之前去除map中包含的workspace.
这是个很奇怪的问题,毕竟没有涉及到对动态图层的查询,但是其他图层显然受到了动态图层的影响, anyway, 这样做了以后就OK了.