跳转到主要内容

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

所有提交的信息确保安全。

  • 关闭 [x]

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

所有提交的信息确保安全。

  • 关闭 [x]

使用 Perl、GD 和 plot-latlong 创建数据的地理标绘

在世界地图和美国地图上开发自定义数据图,包括区域色彩渐变的数据表示

Nathan Harrington 是 IBM 的一位程序员,目前主要从事 Linux 和资源定位技术方面的工作。

简介: 本文使用世界地图和自定义的美国地图、Perl、GD 和 Cooperative Association for Internet Data Analysis (CAIDA) plot-latlong 工具,演示如何在 Google 地图和美国国家地图的内部创建有效的数据可视化表示。

发布日期: 2007 年 6 月 07 日
级别: 中级
访问情况 : 1582 次浏览
评论: 


人员和组织通常需要使用地图表示实现数据可视化。现有的地图工具(例如 Google 地图)提供了优秀的方法(虽然有限)。本文将把简单的 Perl 代码用于使用 Yahoo 的免费地理编码服务进行的地理编码查找。使用已获得的纬度和经度,本文随后将展示如何使用 CAIDA 的 plot-latlong 应用程序以及使用 GD 的注释来制作几乎有无限选项的有用图形。

在构建混合的 plot-latlong 和 Perl-GD 地图后,我们将修改背景地图轮廓。使用 GD 的填充工具和其他工具,我们将创建具有 “色彩渐变” 版本的美国地图,以表示地理点,以及与州相关的数量数据。

本文介绍的工具和技术将使您可以使用开源软件和可免费获得的地理编码服务来创建您自己的自定义地理数据图。现有的地图工具 API 可以让您标绘世界各地的地理点,但是您可能需要一种轻松的方法根据特定数据对州、国家或地区使用色彩渐变效果。您还可能需要为数以千计的地理点实时提供配有可自定义指示器的坐标图。GD、Perl 和 plot-latlong 都是快速创建高效地图所需的工具。

要求

硬件

2000 年后制造的所有 PC 应当能够提供足够的能力编译和运行本文中的代码。CAIDA 的 plot-latlong 和 GD 将执行大部分处理,并且这些程序都经过良好设计而且速度很快。

软件

假定您选择的运行环境包含最新版本的 Perl,您将需要安装 Geocoding 模块和 GD Perl 模块,以及 CAIDA 的 plot-latlong。从您最喜欢的 CPAN 镜像下载并安装 GD 模块。您还需要安装 Geo::Coder:Yahoo Perl 模块及其依赖关系:Yahoo::Search

在把 plot-latlong 压缩包解压缩后,请把 .mapimages 目录和 .mapinfo 文件复制到 ${HOME} 目录中。我们稍后将在多次地图生成步骤中使用这些文件和目录。


地理编码物理地址

出于本文的目的,地理编码 被定义为查找给定地址的纬度和经度。可以用 plot-latlong 创建的大多数有用的数据地图将把详细信息解析为详细的城市或郊区。给定一组地址,我们将查找它们的纬度和经度,然后使用 plot-latlong 把它们显示到世界地图中。考虑以下地址列表:


清单 1. 示例 locationNames 数据文件
                
cary, nc
oswego, ny
potsdam, germany
beijing, china
london, england
bangalore, india
brasilia, brazil

我们将使用的 geocoder 模块和查找服务非常灵巧,因此它知道我们是指美国北卡罗来纳州的凯利市,而不是指新喀里多尼亚的一个名叫卡里的人。考虑用以下脚本来处理 locationNames 数据文件并创建地理编码的数据集:


清单 2. yahooGeoCode.pl
                
#!/usr/bin/perl -w
# yahooGeoCode.pl - lookup long/lat of an address using yahoo
use strict;

use Geo::Coder::Yahoo;
my $geocoder = Geo::Coder::Yahoo->new(appid => 'my_app' );

while( my $line = <STDIN> )
{
  chomp($line);
  my $location = "";
  $location = $geocoder->geocode( location => "$line" );

  for ( @{$location} )
  {
    my %hash = %{$_};
    print "$hash{latitude} $hash{longitude} # $line \n";
  } 
}#while stdin

用命令 cat locationNames | perl yahooGeoCode.pl >cityCoords 运行 geocoder。这将给您提供一个包含经度、纬度和城市名称的文件。您可以使用任何一个所需的 geocoder 来生成 cityCoords 中所需格式的文件。本文选用的是 Ask Bjoern Hansen 提供的 Yahoo/Perl 地理编码模块,是因为它十分优秀并且简单易用。


清单 3. 示例 cityCoords 数据文件
                
35.791458 -78.781174 # cary, nc 
43.455471 -76.510048 # oswego, ny 
52.400002 13.07 # potsdam, germany 
40.25 116.5 # beijing, china 
51.52 -0.1 # london, england 
12.97 77.559998 # bangalore, india 
-15.78 -47.91 # brasilia, brazil 


用 plot-latlong 进行地图注释

plot-latlong 的标准用法

使用 cityCoords 文件中的地理编码记录,您现在可以使用 plot-latlong 程序把它们标绘到世界地图上。确保 plot-latlong.pl 程序位于当前目录中并用命令 cat cityCoords | perl plot-latlong.pl -s 5 >cityMap1.png 运行程序。这将生成一个标准的 plot-latlong 类型的图,其中大矩形表示城市所在位置。

地图的注释

GD 可用于为地图图像文件注释标题和出处文本、图例说明和灵活多变的边界。但是,plot-latlong 的实际功能是它能够返回地理位置的精确像素位置。使用这些像素坐标,我们可以绘制以这些点为起点的直线,重新设定直线的颜色、连接直线、用颜色填充周围的区域或者 GD 可以执行的任何其他操作。例如,我们需要在地图图像的顶部构建一条带图像标识符和文本的路线。从包含图像标识符和文本的每个框中,将向地图中相关的坐标绘制一条直线。清单 4 中说明的自定义 Perl 脚本将自动执行此过程。要生成所需的像素坐标,只需把 -c 选项传递给 plot-latlong,然后像素坐标将被打印到 stderr。再次运行标绘命令:cat cityCoords | perl plot-latlong.pl -s 5 -c >cityMap1.png 2>cityPixels


清单 4. worldCompositeMap.pl,第 1 部分
                
#!/usr/bin/perl -w
# worldCompositeMap.pl - overlay text, images and shapes on map image
use strict;
use GD;

die "specify: pixelFile dataFile sourceImage destImage" unless @ARGV == 4;

my $newMap = newFromPng GD::Image( $ARGV[2] );

my $imageWidth = $newMap->width();
my $imageHeight = $newMap->height();
my $topMargin = 110;
my $blankMap = new GD::Image($imageWidth, $imageHeight+$topMargin);

my $white = $blankMap->colorAllocate(255,255,255);
my $black = $blankMap->colorAllocate(0,0,0);

$blankMap->copy( $newMap, 0,$topMargin, 0,0, $imageWidth,$imageHeight );

my @pixels = ();
my @data = ();
open( PIXELFILE, "$ARGV[0]" ) or die "can't open pixels file";
  while( my $line = <PIXELFILE> ){ push @pixels, $line }
close(PIXELFILE);

open( DATAFILE, "$ARGV[1]" ) or die "can't open data file";
  while( my $line = <DATAFILE> ){ push @data, $line }
close(DATAFILE);

my $posCount = 0;
my $textX = 25;
my $textY = 20;
my $annotateRowIncrement = 150;

worldCompositeMap.pl 程序中的第一部分将检查命令行并且设置背景图像。$blankMap 变量是作为一个新的 GD Image 创建的,其宽度与输入图像相同,顶部有额外的空白用于保存注释信息。然后指定黑色和白色以确保按照预期为图像着色。原始的 plot-latlong 输出地图随后被复制到我们的 blankMap 中,向下移动了 110 像素。

下一部分将把像素坐标装入 @pixels 数组。这些像素值将在 worldCompositeMap.pl 代码的第 2 部分中处理。将以相同方式执行用信息(本例中为位置名称和注释图像名)装入 @data 数组。请注意,这些文件都有相应的顺序入口。像素数据文件中的第 1 行将指定在城市数据文件的第 1 行中指定的地点的坐标。worldCompositeMap.pl 程序的第 2 部分将迭代数据文件并为图像加注。


清单 5. worldCompositeMap.pl,第 2 部分
                
for my $dataLine ( @data )
{
  my( undef, undef, $pointX, $pointY) =  split " ", $pixels[$posCount];
  my( $text, $faceImgName ) = split '##', $dataLine;

  $blankMap->stringFT( $black, '/usr/share/fonts/bitstream-vera/Vera.ttf',
    8,0,$textX,$textY, "$text", 
    {   linespacing=>0.6,
        charmap  => 'Unicode',
    });

  $blankMap->rectangle( $textX-10, 5, $textX+120, 100, $black);
  $blankMap->line($textX+50, 100, $pointX, $pointY+$topMargin, $black );

  my $faceImg = newFromPng GD::Image( $faceImgName );
  $blankMap->copyResized( $faceImg, $textX,$textY+10, 0,0, 60,60, 115,115 );

  $textX += $annotateRowIncrement;
  $posCount++;

}#for each data line

open( TILEOUT,"> $ARGV[3]") or die "can't write $ARGV[3]";
  print TILEOUT $blankMap->png;
close(TILEOUT);

对于数据数组中的每一行,提取图像中的精确像素坐标。从数据数组中采集指定的文本和注释图像文件名,并把指定的文本写入到图像中。当把文本绘制到图像上后,请用一个细黑框框起该文本,然后绘制一条从框的底部到相关数据点的直线。

接下来将把注释图像调整后的版本装入并复制到指定文本下面的框中。然后,把 “当前” 位置朝图像的右侧增加指定的长度,并重复执行此过程。在写出图像后,程序将终止,生成以下输出:


图 1. worldCompositeMap.pl 输出示例
worldCompositeMap.pl 输出示例

要构建图 1 中所示的图像文件,请运行命令 perl worldComposite.pl cityPixels locationNames cityMap1.png worldCityMap_done.png


用 plot-latlong 实现描绘主体的色彩渐变

一般策略

除了简单地标绘地理点外,为美国地图中各个州显示色彩渐变效果也是一种提供信息的有效方法。以下代码和过程描述将展示一种相对简单的方法,用于修改地图图像和 plot-latlong 程序,使您可以创建有用的具有色彩渐变效果的美国地图。

地图图像修改

要使用简单的 GD->Fill 命令实现州(或任何其他描绘的主体)的色彩渐变效果,该地域的内域必须毗邻。如果曾经使用过 Redmond Paint 或 The Gimp 中的 “Paint Bucket” 工具,则会熟悉这种工具的工作原理。

特别地,对于州地图,地图上的州界必须经过修改才能与填充命令良好地结合使用。可以结合 Edge Enhance 效果和州界的像素级别的编辑来完成修改。确保密西根上半岛与马里兰的半数土地相连。您可以自己执行这些修改,也可以使用提供的图像和坐标文件来填充各个州。坐标文件 “state.coords” 只是一个 GD->Fill 命令的起始经度/纬度对(通常是州的首府)。要创建具有色彩渐变效果的特定地理区域地图或整张世界地图,您将需要确保进行图像编辑的区域都是毗邻的,并且为每个渐变的地区开发一个坐标文件。

修改配置文件

把修改后的美国各州的图像文件 (statemap.png) 从 下载 部分复制到 ~/.mapimages 目录中。接下来,您将需要修改 ~/.mapinfo 文件,让 plot-latlong 了解新地图的信息。把下面几行复制到 ~/.mapinfo 文件中:


清单 6. ~/.mapinfo 配置
                
MAP statemap statemap.png 50 -125 24 -66
MAP temporary temporary.png 50 -125 24 -66
PROJECTION statemap ALBER 2812.7  30.8 45.5 21.7 -99.9 929 1561
PROJECTION temporary ALBER 2812.7  30.8 45.5 21.7 -99.9 929 1561

标绘 plot-latlong 修改

在合并州的过程中,将创建 temporary.png 文件。请注意,statemap.png 文件是基于 USA200.png 地图的。如果按需生成可视化地图(例如,在 Web 页面中),您可能会发现使用较小的地图对于缩短处理时间十分有用。对于新增的区别,plot-latlong 程序需要经过修改才能绘制蓝色圆圈而不绘制红色方框。这将提供另外一个级别的信息并且使用 GD 能够很轻易完成。在 plot-latlong 中,注释掉清单 7 中的代码行并插入清单 8 中的代码行。


清单 7. plot-latlong 正方形
                
    $map->filledRectangle($left_x, $top_y,
        $left_x + $point_size - 1, $top_y + $point_size - 1,
        $red);


清单 8. plot-latlong 圆形
                
    my $blue = $map->colorAllocate(64,64,255);
    $map->filledEllipse( $left_x + ($point_size/2), $top_y + ($point_size/2),
         $point_size, $point_size,
         $blue)

色彩渐变的 plot-latlong 修改

把 plot-latlong 文件复制到名为 fillState_plot-latlong 的文件中。打开此文件并删除清单 8 中的代码行。在同一位置中插入清单 9 中的代码行来填充毗邻区域,而不要绘制椭圆形或矩形。

    my $color = $map->colorAllocate(255, 255 - $value, 8);
    $map->fill( $left_x, $top_y, $color);

您还需要把代码行 my ($lat, $long) = split /\s+/; 修改为 my ($lat, $long, $value) = split /\s+/;。这一行更改将允许读入百分数值,该值将决定上面显示的渐变百分数。

示例百分数数据文件

要有效地使用 fillState_plot-latlong 代码,必须构造一个适当的数据文件。完成此操作的一种简单方法是缩小要表示的数据范围,让其范围全部能用 0 到 100 的值来表示。在本例中,值 0 将生成一种较深的橙色,而值 100 将为普通的橙黄色。这种方法将提供每个州的大小的相对直观的信息,并为信息型渐变提供合理的范围。清单 9 将用 0 到 100 的百分数来显示与每个州相关的数据。


清单 9. 示例 usStatePercs 文件
                
32.22434 -86.20379 75 #../../data/coords/AL.MONTGOMERY_
44.33064 -69.72971 98 #../../data/coords/ME.AUGUSTA_
33.51623 -112.02711 7 #../../data/coords/AZ.PHOENIX_
34.72240 -92.35407 11 #../../data/coords/AR.LITTLE_ROCK_
...

使用 参考资料 中提供的 state.coords 文件或在每个州界内部创建您自己的一列坐标。您可以用以下命令构建类似清单 9 的样例百分数文件:

cat state.coords | \
perl -lane '$r=int(rand(99));print "$F[0] $F[1] $r $F[2]"' >usStatesPercs

usStatesPercs 文件现在包含填充的起始位置的坐标,以及相关州的相应渐变百分数。下一项任务是用清单 10 中所示的命令构建标绘了城市的美国各州渐变并加了注释的地图。第一条命令将构建色彩渐变的美国各州地图。第二条命令将把此地图复制到 ~/.mapimages 目录中,以用作下一步的基准地图。类似于标绘上面的世界地图,后续命令将在州渐变地图中标绘大型蓝色椭圆形,同时在图像中记录各自的像素坐标。使用这些像素坐标用于渐变标绘的地图中,随后图像将被加注普通框、图像和直线。


清单 10. 用于构建州渐变、加注的合成地图的命令
                
cat usStatesPercs | perl fillState_plot-latlong -m statemap -s 7 >usStates1.png

cp usStates1.png ~/.mapimages/temporary.png

cat usStatesCoords | \
  perl plot-latlong -m temporary -s 20 -c >usStates2.png 2>usStatesPixels

perl stateCompositeMap.pl usStatesPixels stateData \
  usStates2.png usStatesFinal.png

通过清单 10 中的命令创建的输出图像:


图 2. stateCompositeMap.pl 输出示例
stateCompositeMap.pl 输出示例

stateCompositeMap.pl 程序可从 下载 部分下载。stateCompositeMap.pl 与 worldCompositeMap.pl 程序非常相似 —— 其修改主要是在把各种注释组件与各种尺寸的基本图像对齐。


结束语

使用这些技术、地理编码模块和地图工具,您有无数种选择可以创建按地区色彩渐变和按城市标绘的地图。考虑修改 plot-latlong 数据文件以读入除了数据值和位置以外的各种因素,并且可以创建更多不同种类的地图。使用 GD 在地图上的特定点绘制饼图而不绘制矩形或椭圆形。在像素坐标与 GD 之间创建连接,并填充出差销售人员所跨越的地区。考虑在该地理点根据组织中的员工数围绕指定城市进行阿尔法混合辐射式扫描。使用提供的像素数据来自动创建各个地区的可单击图像地图。随时间变化标绘数据,并使用 mencoder 创建图像的动态影像,等等。plot-latlong 和 GD 几乎提供了无数的方法实现数据可视化。



下载

描述名字大小下载方法
本文的 GD 图os-perlgdPlots_20070223.zip19KBHTTP

关于下载方法的信息


参考资料

学习

  • 您可以参阅本文在 developerWorks 全球站点上的 英文原文

  • CPAN 托管着 GD Image Processing Perl 模块。

  • 访问 Perl-LDAP,了解关于 Perl 和 LDAP 的更多信息。

  • 阅读 Paul Dwerryhouse 撰写的标题为 “An Introduction to perl-ldap” 的文章。

  • 可以在 OpenLDAP 获得大量背景知识和实现知识。

  • PHP.net 是 PHP 开发人员的资源。

  • 查阅 “PHP 推荐读物列表”。

  • 需要把数据库与 PHP 结合使用?请查阅 Zend Core for IBM,这是一个支持 IBM® DB2® 9 的无缝、即用且易于安装的 PHP 开发及生产环境。

  • 浏览 developerWorks 上的所有 PHP 文章PHP 教程

  • 查阅 IBM developerWorks 的 PHP 项目资源 提高 PHP 技巧。

  • 要收听针对软件开发人员的有趣访谈和讨论,访问 developerWorks 的 podcast

  • 随时关注 developerWorks 的 技术事件和网络广播

  • 查阅最近将在全球举办的面向 IBM 开放源码开发人员的研讨会、展览、网络广播和其他 活动

  • 访问 developerWorks 开放源码专区,获得丰富的 how-to 信息、工具和项目更新,帮助您用开放源码技术进行开发,并与 IBM 产品结合使用。

获得产品和技术

讨论

关于作者

Nathan Harrington 是 IBM 的一位程序员,目前主要从事 Linux 和资源定位技术方面的工作。

关于报告滥用的帮助

报告滥用

谢谢! 此内容已经标识给管理员注意。


关于报告滥用的帮助

报告滥用

报告滥用提交失败。 请稍后重试。


developerWorks:登录


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 使用条款

 


当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

请选择您的昵称:

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

(长度在 3 至 31 个字符之间)


单击提交则表示您同意developerWorks 的条款和条件。 使用条款.

 


为本文评分

评论

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Open source
ArticleID=226127
ArticleTitle=使用 Perl、GD 和 plot-latlong 创建数据的地理标绘
publish-date=06072007
author1-email=harrington.nathan@gmail.com
author1-email-cc=

标签

Help
使用 搜索 文本框在 My developerWorks 中查找包含该标签的所有内容。

使用 滑动条 调节标签的数量。

热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。

我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。

使用搜索文本框在 My developerWorks 中查找包含该标签的所有内容。热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。