随笔-18  评论-20  文章-0  trackbacks-0
 

主要功能

1、可以在地图上点击一个起点城市,自动画出从该城市出发的所有航线;也可以通过文本框输入起点城市进行查询,然后绘制航线;

2、将查询结果显示给用户。当用户选择一条具体的航线时,列出该航线的相关信息,包括起点城市、终点城市、出发时间、到达时间、票价等;

3、根据需要,用户可以高亮显示某条航线,另外还有ZoomTo等功能。

数据准备

1、航线的相关数据,google了一部分南航的数据,虽然少,但是做demo也差不多了。其中票价、起飞时间和到达时间是为了演示需要添加的三个字段。

      出发城市  到达城市    票价        起飞时间    到达时间

 1 | 海口     | 北京     | 1201.00 | 8:35    | 14:35

 2 | 海口     | 广州     | 1202.00 | 8:35    | 14:35

 3 | 海口     | 深圳     | 1203.00 | 8:35    | 14:35

 4 | 海口     | 南京     | 1204.00 | 8:35    | 14:35

 5 | 海口     | 贵阳     | 1205.00 | 8:35    | 14:35

 6 | 海口     | 成都     | 1206.00 | 8:35    | 14:35

 7 | 海口     | 上海     | 1207.00 | 8:35    | 14:35

 8 | 海口     | 郑州     | 1208.00 | 8:35    | 14:35

 9 | 海口     | 长沙     | 1209.00 | 8:35    | 14:35

 10 | 海口     | 西安     | 1210.00 | 8:35    | 14:35

 11 | 海口     | 昆明     | 1211.00 | 8:35    | 14:35

 12 | 海口     | 温州     | 1212.00 | 8:35    | 14:35

 13 | 海口     | 大连     | 1213.00 | 8:35    | 14:35

 14 | 海口     | 武汉     | 1214.00 | 8:35    | 14:35

 15 | 海口     | 沈阳     | 1215.00 | 8:35    | 14:35

 16 | 海口     | 哈尔滨   | 1216.00 | 8:35    | 14:35

 17 | 海口     | 重庆     | 1217.00 | 8:35    | 14:35

 18 | 海口     | 南昌     | 1218.00 | 8:35    | 14:35

 19 | 海口     | 乌鲁木齐 | 1219.00 | 8:35    | 14:35

 20 | 北京     | 重庆     | 1220.00 | 8:35    | 14:35

 21 | 北京     | 成都     | 1221.00 | 8:35    | 14:35

 22 | 北京     | 南昌     | 1222.00 | 8:35    | 14:35

 23 | 北京     | 长沙     | 1223.00 | 8:35    | 14:35

 24 | 北京     | 乌鲁木齐 | 1224.00 | 8:35    | 14:35

 25 | 北京     | 三亚     | 1225.00 | 8:35    | 14:35

 26 | 北京     | 延吉     | 1226.00 | 8:35    | 14:35

 27 | 北京     | 昆明     | 1227.00 | 8:35    | 14:35

 28 | 西安     | 榆林     | 1228.00 | 8:35    | 14:35

 29 | 西安     | 银川     | 1229.00 | 8:35    | 14:35

 30 | 西安     | 南京     | 1230.00 | 8:35    | 14:35

 31 | 西安     | 长沙     | 1231.00 | 8:35    | 14:35

 32 | 西安     | 海口     | 1232.00 | 8:35    | 14:35

 33 | 西安     | 深圳     | 1233.00 | 8:35    | 14:35

 34 | 西安     | 广州     | 1234.00 | 8:35    | 14:35

 35 | 深圳     | 成都     | 1235.00 | 8:35    | 14:35

 36 | 深圳     | 重庆     | 1236.00 | 8:35    | 14:35

 37 | 深圳     | 武汉     | 1237.00 | 8:35    | 14:35

 38 | 深圳     | 宜昌     | 1238.00 | 8:35    | 14:35

 39 | 深圳     | 襄樊     | 1239.00 | 8:35    | 14:35

 40 | 温州     | 南京     | 1240.00 | 8:35    | 14:35

 41 | 温州     | 烟台     | 1241.00 | 8:35    | 14:35

 42 | 温州     | 厦门     | 1242.00 | 8:35    | 14:35

 43 | 温州     | 赣州     | 1243.00 | 8:35    | 14:35

把这些数据导入到数据库的airlines表中。

2、用作地图显示的行政区划图以及城市的点要素图。为了简化,只选择了涉及上述航线的若干城市。城市数据是一个pointshapefile文件,其中有一个属性列为城市名称“name”,为了方便检索,name属性中保存的城市名称与数据库中航线信息所保存的城市名称是匹配的。

实现方法

ADF提供了很好用的task framework,因此这个例子以自定义task的形式实现。先来简单了解一下整个操作的流程:

用户选择了自定义工具栏提供的一个工具,与地图进行一个点查询的交互,选择一个起点城市。在服务器端根据用户的操作将得到一个点的坐标,根据这个坐标进行查询,得到这个坐标点所表示的点要素的相关信息,这里我们所关心的只是这个城市的名称。知道了城市名称以后,以它作为起点城市,到数据库中检索所有从该城市出发的航线的目的地城市。这是一个字符串类型的数组,接下来可以根据这些城市名到地图中查找它们对应的点要素,并获得这些点要素的坐标。这样,我们就有了一个起点和若干个终点的坐标,可以绘制航线了。好了,基本思路就是这样,来看看怎么实现J

先创建一个自定义task类,它有一个方法:

public class SearchAirlinesTask{

public void getAirlines(MapEvent event){

}

}

声明了这个类以后,task framework就会根据getAirlines(MapEvent event)方法的参数来判断这个工具的类型。由于MapEvent涉及的地图交互操作有很多种,而这里我们需要的是点查询操作,所以接下来我们需要再构造一个类来给自定义task加一些说明:

public class SearchAirlinesTaskInfo extends SimpleTaskInfo{

private TaskToolDescriptor[] taskTool = new TaskToolDescriptor[1];

 

public SearchAirlinesTaskInfo(){

     taskTool[0] =

new TaskToolDescriptor(SearchAirlines.class,"getAirlines","选择起点",ClientActions.MAP_POINT);

     taskTool[0].setToolTip(“从地图上选择一个起点”);

}

public TaskToolDescriptorModel[] getToolDescriptors(){

     return taskTool;

}

}

然后将这个taskInfo类添加到我们的自定义task中:

public class SearchAirlinesTask{

private SearchAirlinesTaskInfo taskInfo = new SearchAirlinesTaskInfo();

public void getAirlines(MapEvent event){

}

 

public SimpleTaskInfo getTaskInfo(){

    return taskInfo;

}

}

完成了上面的准备步骤以后,我们深入到getAirlines(MapEvent event)方法的内部,看看它是怎么运行的:

public getAirlines(MapEvent event){

WebContext ctx = event.getWebContext();

WebGraphics graphics = ctx.getWebGraphics();

WebQuery query = ctx.getWebQuery();

}

所有的查询操作都是通过WebQuery来进行的,查询的结果将通过WebGraphics绘制到地图上。查询的时候需要提供两个信息,点的坐标以及目标图层:

WebPoint point =

(WebPoint)event.getWebGeometry().toMapGeometry(ctx.getWebMap());

IdentifyCriteria ic = new IdentifyCriteria(point);

ic.setMaxRecordCount(1);

//只需要查询city图层,该图层保存的是城市的相关信息

List layers = query.getQueryLayers();

List<WebLayerInfo> queryLayer = new ArrayList<WebLayerInfo>();

for(Iterator iter=layers.iterator(); iter.hasNext();){

Object item = iter.next();

if(item instanceof WebLayerInfo){

     WebLayerInfo layerinfo = (WebLayerInfo)item;

     if(layerinfo.getName().equals(“city”)){

         queryLayer.add(layerinfo);

     }

}

}

 

List rs = query.query(ic, queryLayer);

ok,用户与地图交互操作的查询就完成了,接下来我们需要从查询结果中得到这个城市的城市名。

if(rs.size() > 0){

Iterator iter = rs.iterator();

QueryResult item = (QueryResult)iter.next();

Object obj = item.getDetails().get(“name”);

String startCity = obj.toString();

WebPoint start = (WebPoint)item.getHighlightGeometry();

}

这里需要解释一下的是最后一句,也许有人会问,刚才我们不是已经获取了一个point坐标了吗,那个不就是起点城市么?事实上,我们在地图上点击查询的时候不会恰好就点在表示城市的那个点的中心,WebQuery查询的时候是有一个距离容错的。而绘制航线的时候要求更精确,所以我们以查询得到的点要素的坐标为准。

费了半天劲总算把城市名给找出来了,擦一把汗,接着查,我们还需要终点城市的坐标呢!刚才我们用的是WebGeometry来查询,接下来我们将使用文本进行查询。

DbAirlineSearch dboper = new DbAirlineSearch();

String[] destinations = dboper.getDestinations(startCity);

//终点城市的坐标

WebPoint[] ends = new WebPoint[destinations.length];

//航线

WebPath[] airlines = new WebPath[destinations.length];

//WebGraphics中绘制航线所需的要素

GraphicElement[] linesElements =

new GraphicElement[destinations.length];

 

for(int i=0;i<destinations.length;i++){

//设置文本查询的条件

TextCriteria tc = new TextCriteria();

List<String> searchFields = new ArrayList<String>();

searchFields.add(“name”);

tc.setSearchFields(searchFields);

tc.setSearchText(destinations[i]);

 

List rs2 = query.query(tc,queryLayer);

//处理文本查询的结果

if(rs2.size() > 0){

     QueryResult destination = (QueryResult)rs2.iterator.next();

     ends[i] = (WebPoint)destination.getHighlightGeometry();

    //得到一个终点坐标以后就可以绘制一条航线了

     List<WebPoint> pointList = new ArrayList<WebPoint>();

     pointList.add(start);

     pointList.add(ends[i]);

     airlines[i] = new WebPath(pointList);

     WebPolyline polyline = new WebPolyline();

     polyline.addPath(airlines[i]);

 

     linesElement[i] = new GraphicElement();

     linesElement[i].setGeometry(polyline);//这里需要说明一下,如果这里用的是WebPath,将不会绘制出航线,换成WebPolyline以后就可以了。

     linesElement[i].setSymbol(lineSymbol);

     graphics.addGraphics(linesElement[i]);

}

}

好了,getAirlines(MapEvent event)方法大致就是这样,完成以后就可以在地图上进行交互查询了,选择某个城市以后就可以自动绘制出该城市出发的航线。

但是玩了几次以后,发现这个demo还可以有些扩展。比如可以将查询的结果保存在WebResults中,可以让用户点击某个航线记录,然后显示出该航线的相关信息,像起飞时间、到达时间、票价等等;另外,用户可能还有兴趣高亮显示某条记录,甚至用用ZoomTo功能啊。

仔细考虑一下,其实刚才我们已经做了很多准备工作了呀。首先,已经查询得到了起点和终点城市,根据这两个城市的名称我们就可以从数据库中查询到这条航线的其他相关信息;其次,绘制航线时创建了GraphicElement来表示线要素,这个线要素中包含了WebPolyline的信息,可以用来进行高亮和ZoomTo等操作。哈哈,现在我们来充分利用这些已有数据。

首先要创建一个辅助类,用来记录每次查询操作的结果:

public class SearchAirlinesTaskResult{

private static WebSimpleLineSymbol highlightSymbol;

private WebContext ctx;

private GraphicElement originElement; //航线的原始符号

private WebPolyline polyline;

private GraphicElement highlightElement; //高亮线的符号

private String startCity;

private String endCity;

private Map<String,String> details; //航线的详细信息

 

static{

     highlightSymbol = new WebSimpleLineSymbol();

     highlightSymbol.setWidth(2);

     highlightSymbol.setColor(“234,244,34”);

     highlightSymbol.setLineType(WebSimpleLineSymbol.SOLID);

}

 

public SearchAirlinesTaskResult(WebContext context, GraphicElement originElement){

    this.ctx = context;

    this.originElement = originElement;

    this.polyline = (WebPolyline)originElement.getGeometry();

}

 

public Map getDetails(){

if(details == null){

     DbAirlineSearch dboper = new DbAirlineSearch();

     details = dboper.getDetails(startCity, endCity);

 }

return details;

}

//startCityendCitygettersetter 方法

……

public String getDescription(){

return startCity + “ ” + endCity;

}

 

//highlight的实现方法就是从WebGraphics中删除原有的线型符号,用新的高亮线型符号重绘一次

public void highlight(){

     WebGraphics graphics = ctx.getWebGraphics();

     graphics.removeGraphics(originElement);

    

     highlightElement = new GraphicElement();

     highlightElement.setGeometry(polyline);

     highlightElement.setSymbol(highlightSymbol);

     graphics.addGraphics(highlightElement);

     ctx.refresh();

}

public void clearHighlight(){

     WebGraphics graphics = ctx.getWebGraphics();

     if(highlightElement != null){

         graphics.removeGraphics(highlightElement);         

     }

     graphics.addGraphics(originElement);

     ctx.refresh();

}

//根据polyline获取其外包矩形,然后刷新地图

public void zoomTo(){

     WebExtent ext = getExtent(polyline);

     ctx.getWebMap().setCurrentExtent(ext);

     ctx.refresh();

}

}

 

有了这个辅助类以后,只需要在前面的getAirlines(MapEvent event)方法中添加以下代码:

……

ArrayList<SearchAirlinesTaskResult> results =

new ArrayList<SearchAirlinesTaskResult>();        

for(int i=0;i<destinations.length;i++){

//设置文本查询的条件

TextCriteria tc = new TextCriteria();

List<String> searchFields = new ArrayList<String>();

searchFields.add(“name”);

tc.setSearchFields(searchFields);

tc.setSearchText(destinations[i]);

 

List rs2 = query.query(tc,queryLayer);

//处理文本查询的结果

if(rs2.size() > 0){

     QueryResult destination = (QueryResult)rs2.iterator.next();

     ends[i] = (WebPoint)destination.getHighlightGeometry();

     //得到一个终点坐标以后就可以绘制一条航线了

     List<WebPoint> pointList = new ArrayList<WebPoint>();

     pointList.add(start);

     pointList.add(ends[i]);

     airlines[i] = new WebPath(pointList);

     WebPolyline polyline = new WebPolyline();

     polyline.addPath(airlines[i]);

 

     linesElement[i] = new GraphicElement();

     linesElement[i].setGeometry(polyline);//这里需要说明一下,如果这里用的是WebPath,将不会绘制出航线,换成WebPolyline以后就可以了。

     linesElement[i].setSymbol(lineSymbol);

     graphics.addGraphics(linesElement[i]);

    

                     //将查询结果添加到QueryResult

            SearchAirlinesTaskResult searchRs =

                        new SearchAirlinesTaskResult(ctx,linesElement[i]);

            searchRs.setFromcity(fromcity);

            searchRs.setDestination(destinations[i]);

     results.add(searchRs);

}

}

HashMap<String,String> actions = new HashMap<String,String>();

actions.put("高亮显示", "highlight");

actions.put("取消高亮", "clearHighlight");

actions.put("ZoomTo", "zoomTo");

           

ctx.getWebResults().addResultsWithActionMap("航线查询结果", results,

 "getDescription", "getDetails", actions);    

ctx.refresh();

 

最终的效果图如下:

 

 

posted on 2007-08-18 15:46 JavaPoint 阅读(3203) 评论(1)  编辑  收藏 所属分类: ArcGis

评论:
# re: ArcGis 航线查询完全例子[未登录] 2008-12-17 19:24 | king
请问下楼主上面的的查询是不是先要把airlines与城市数据建产join连接,我是初学者只是感觉  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: