当前项目中的优惠促销信息需要和地图位置相关起来,所以就用到了google map。根据需求,要做一个在地图上显示郑州地区所有优惠促销信息的页面。首先对这个需求进行了分析,郑州的优惠促销信息是非常多的,如何在地图上将所有的信息显示出来?如果全部显示出来,将会出现信息的压盖和信息将地图压盖起来,用户看不到地图,也看不清楚信息。所以就需要一定的处理。

            网上通行的做法就是对地图上显示的信息进行分页展示,这样在页面上显示的信息就不会很多,用可以很清晰的看到地图和地图上所展示的信息。如google map


其它的都是同样的方式,只是显示的样式有所不同。

            Google map还提供了另一种方式,


将所有的信息都呈现在地图上,google map所呈现的所有信息点是绘制在图片上的,也就是说,google map的开发人员利用api有开发和制作了一个图层,和影像、纹理是同一级别的图片索引集合,数据传送到本地浏览器,这样数据不用做显示,提高了浏览器的速度,也完成了信息的查询。如果利用google map提供的marker来做,显然数据量是非常巨大的,浏览器无法承受如此多的marker对象的绘制。所以google map才用了静态图片来实现。

 

            我们也想在地图上显示所有的数据,但是我们没有google那么强大的实力,说以就仿照了google 高考2009地图:


将信息聚合显示在地图之上,也就是说在某一位置,告诉用户这个地方有多少优惠促销信息,你可以放大或点击进入进行查看。

            目标有了之后就开始研究如何实现。我的测试数据是100万条优惠促销信息。

 

初始实现方法:根据查询,将所有符合条件的数据读取出来,通过ajax发送到前台,然后在前台进行相交压盖判断。

试验结果是一次读取的数据量太大,消耗太多的时间,另一个就是数据读取完成之后发送到前台占用大量的带宽。再有就是前台浏览器运算压盖消耗太多的时间。

经过试验,不可行,需要进行改进,不过流程上没有太大的问题。所以感觉的思路如下:

1、 减少数据库中读取出来的数据进行。

2、 在前台建立格网索引,加快计算压盖速度。

经过分析,如果减少数据库读取出来的数据,那就没有在地图上显示或提示出网站所有的优惠促销信息,在前台建立格网索引,依然需要将大量的数据传送到前台,那为什么不在后台建立格网索引呢。分析过后,将格网索引放在后台进行处理。经过改进,是比第一次有所提高,但还不够。

 

经过一系列的试验分析思考之后,得出了解决方案。

将格网索引放置在数据库中,一个查询就可聚合分组查询出所以优惠促销。减少数据的读取和网络间的传送,简化前台开发(oracle 有支持地理实体的组件,Oracle Spatial,但是对于这个需求并不实用)

具体方法如下:

1、 google map区域的建立格网

因为google map的缩放分级,所以,建立格网时需要根据不同的级别进行创建。当前所做的指真对郑州地图,所以格网重12级到19级。如图:


12级为16*16的格网

13级为32*32的格网

….

格网的递增为四叉树。因为从12级开始就需要显示丰富的信息,说以第一级不是一个2*2的网格,而是一个15*15的网格。


格网个2维的数组,将其转换为1维数组,即12级格网号顺序从1开始到256结束。第一排从116,第二排从17-32以次类推,最终完成格网的模型创建。

下边开始对数据库进行设计。

创建数据表。

字段

类型描述

信息id

关联的信息id

Lev12

整型格网号

Lev13

整型格网号

Lev14

整型格网号

Lev15

整型格网号

Lev16

整型格网号

Lev17

整型格网号

Lev18

整型格网号

Lev19

整型格网号

通过计算,将二维的点状信息转换为相应级别下的格网好

insert into shopindex (shopid) values (sid);

    --更新索引

    update shopindex s

       set (lev12, lev13, lev14, lev15, lev16, lev17, lev18, lev19) = (select GetGirdNo(px,

                                                                                        py,

                                                                                        12 - 12) lev12,

                                                                              GetGirdNo(px,

                                                                                        py,

                                                                                        13 - 12) lev13,

                                                                              GetGirdNo(px,

                                                                                        py,

                                                                                        14 - 12) lev14,

                                                                              GetGirdNo(px,

                                                                                        py,

                                                                                        15 - 12) lev15,

                                                                              GetGirdNo(px,

                                                                                        py,

                                                                                        16 - 12) lev16,

                                                                              GetGirdNo(px,

                                                                                        py,

                                                                                        17 - 12) lev17,

                                                                              GetGirdNo(px,

                                                                                        py,

                                                                                        18 - 12) lev18,

                                                                              GetGirdNo(px,

                                                                                        py,

                                                                                        19 - 12) lev19

                                                                         from ooshop f

                                                                        where s.shopid = f.id)

     where s.shopid = sid;

 

根据xylev获取格网号函数

create or replace function GETGIRDNO(x   in integer,

                                     y   in integer,

                                     lev in integer)

return integer is

 girdnum   INT := 15;

 width     INT := 110866;

 height    INT := 77900;

 gnum      INT;

 stpwidth int;

 stpheight int;

 xmin      int := 40869800;

 ymin      int := 12467548;

 col       int;

 row       int;

 res       int;

BEGIN

 

 gnum      := girdnum * POWER(2, lev);

 stpwidth := width / gnum;

 stpheight := height / gnum;

 col       := (x - xmin) / stpwidth;

 row       := (y - ymin) / stpheight;

 

 res := col + row * gnum;

 if res < 0 or res >girdnum*girdnum * POWER(4, lev) then

    res := 0;

 end if;

 return res;

 

END GetGirdNo;

 

信息如图


有了这个索引表之后,就可以用oracle的分组查询,一个查询将给定范围的数据进行分组查询出来,分组的依据就个格网,这样查询出的数据就是在这个格网下有多少条优惠促销信息。

获取12级的分组数据

select lev12,count(shopid) from shopindex t group by lev12


真正的查询要比这复杂点,要根据给定的地图范围进行查询,这样就需要一个函数,即根据地图范围获取这个范围下的所有格网。函数如下:

create or replace function GETGIRDNOS(stcol in integer,

                                      strow in integer,

                                      encol in integer,

                                      enrow in integer,

                                      lev   in integer)

RETURN colrows IS

  gnum    int;

  i       int;

  j       int;

  girdnum INT := 15;

  colrow  colrows := colrows();

BEGIN

  i := strow;


  gnum := girdnum * POWER(2, lev);

  while (i <= enrow) loop

    j := stcol;

    while (j <= encol) loop

      colrow.EXTEND;

      colrow(colrow.COUNT) := j + i * gnum;

      j := j + 1;

    end loop;

    i := i + 1;

  end loop;

  RETURN colrow;

END GetGirdNos;

 

 

数据的读取

      var result = new Collection<ooBFeature>();

            while (reader.Read())

            {

                ooBFeature gm = new ooBFeature(1);

                gm.I = reader.GetInt32(0);

                gm.N = reader.GetValue(1).ToString();

                int row = (int)(gm.I / grid.GNum);

                int col = (int)(gm.I % grid.GNum);

                gm.X = col * grid.StpWidth + grid.StpWidth / 2 + ooGridModel.x;

                gm.Y = row * grid.StpHeight + grid.StpHeight / 2 + ooGridModel.y;

                result.Add(gm);

            }

            return result;

根据读取出的格网计算出地图上的坐标。以上就是用oracle建立地理信息索引的方法,如有问题,可进行交流。

 效果页面http://www.map85.com/map

 


 

 梦开始的地方---图帮网www.map85.com