我使用REST接口的新技术来提供新的地理编码加载项。其核心是对相应REST接口的调用 MapQuest ,一家提供大量路由服务和应用程序的公司。
MapQuest的服务之一是路由。对于提供的每对地址,MapQuest会发回每个位置的纬度和经度以及诸如国家和州之类的管理信息。它还提供了两个点之间所有航路点的位置,以及从第一个地址到第二个地址的更改方向的位置。还提供摘要信息,例如总距离和估计的行驶时间。如果仅使用两个地址调用该函数,则它将返回它们之间的路径和/或距离。如果提供地址列表,则将为每对连续的列表元素计算路由。然后将在元素1和元素2之间,在元素2和元素3之间给出连接,依此类推。n个位置的列表将产生n-1条路线。
由于数据表是收集信息的常用方式 JMP ,分析开始于用户通过用户对话框将角色分配给数据表的列。的地理编码2020插件以相同的方式工作。用户完成对话框后,程序将从数据表中收集相关数据,将其转换为REST API所需的结构,然后将其发送到MapQuest。因此,该程序的大致结构是:1)完成用户对话框,2)收集数据,3)为接口准备数据,4)发送接口请求,5)解释结果,6)编写JMP数据表。第三步,数据准备,定义为一个函数,可以作为 MapQuest_route.jsl 在JSL食谱中。您可以将其嵌入自己的地理应用程序中,或使用它来获取有关如何为REST调用构造数据的想法。
基准功能
您或您程序的任何用户都需要 API密钥来自MapQuest。
JMP数据以数据表列的形式出现,而REST接口最有可能使用JSON结构。结果,需要具有在两种格式之间转换的功能。JSL还具有用于数据收集的结构,可以是列表或关联数组。此功能的目的是封装所有非本机JSL命令。典型的JSL变量以字符,数字或列表格式提供了必要的数据。调用返回的数据也包含在JSL列表中。因此,将此功能嵌入JSL脚本不需要JSL标准以外的任何其他知识。
介面
使用如下语句调用JSL函数:
结果= function();
如果函数需要或接受参数,则将其列在括号中。可以使用大括号或完整参数列表调用此函数GC_route。用括号括起来的调用将调用一个参数定义窗口,其中包含输入和输出的轮廓,如以下各节所示:

函数调用中的参数始终是位置参数。使用参数调用该函数时,需要提供所有必填参数,但它们可以为空。
在我的关于我的地理编码插件的博客文章 ,我使用了家乡周围的一些当地旅游景点作为如何使用外接程序的示例。让我们来看看其中两个,看看这个接口是如何工作的:

|
Alte Freiheit 24a,42103 Wuppertal,德国
|
伍珀塔勒Schwebebahn铁路(Wuppertaler Schwebebahn)是一条长达13公里的悬索铁路,这是世界上最古老的悬挂汽车的高架电气铁路,于1901年启用。
|

|
Schloßplatz2,42659索林根,德国
|
城堡城堡(Schloss Burg),始建于十二世纪日世纪。
|
首先,您需要MapQuest的访问密钥,假设它是1234ABCD。另外,假设:
- 每个地址只是一个文本字符串。
- 您提供了一对地址字符串;不涉及数据表。
- 您想乘汽车旅行。
- 您只对距离和旅行时间感兴趣。
- 您想要以英里为单位的距离。
使用此接口的一种方法是直接获取地址字符串。在这种情况下,格式指示符(位置2)必须为1或更大。然后,函数调用如下所示:
routes = GC_route ("1234ABCD", "", 1, "fastest", "m", {"Alte Freiheit 24a, 42103 Wuppertal, Deutschland",<BR /> "Schloßplatz 2, 42659 Solingen, Deutschland"}, {}, {}, {}, {}, {}, {});
如果地址不是在一个字符串中,而是在单独的元素中,则格式指示符必须为0(零),这意味着您的调用将类似于:
routes = GC_route ("1234ABCD", "", 0, "fastest", "m", {}, {"Deutschland", "Deutschland"}, {},
{"Wuppertal", "Solingen"}, {42103, 42659}, {"Alte Freiheit 24a", "Schloßplatz 2"}, {})
当然,您不需要将值作为参数放入;您还可以提供一个变量,例如带有国家名称列表的列表变量。

无论如何,结果都是相同的数据列表:
{200, "HTTP/1.1 200 OK", "", {}, {""}, {51.256414, 51.137675}, {7.148503, 7.152488}, {"close", "exact"},{"DE", "DE"},<BR />{"North Rhine-Westphalia", "North Rhine-Westphalia"}, {"Wuppertal", "Solingen"}, {"42103", "42659"},<BR /> {"Elberfeld", "Unterburg"}, {"Alte Freiheit", "Schloßplatz 2"}, {., 16.002}, {., 1600}, {}, {}, {0, 1}, [=>], }
找到两个位置,并计算距离和行驶时间。因此,参数五是带有空字符串的列表。最后,有一个用于空关联数组的符号([=>])。它为空,因为参数13(详细信息标志)设置为零。否则,可以在此阵列中找到路由信息。
调用的参数列表中的微小更改会导致输出中的重大更改。这就是参数13(“ detail”标志)的更改。如果将其设置为1,则通过包含所有路由信息的数组扩展输出:
{200, "HTTP/1.1 200 OK", "", {}, {""}, {51.20971, 51.21327}, {7.07255, 7.08376},{"exact", "exact"}, {"DE", "DE"},<BR /> {"Nordrhein-Westfalen", "Nordrhein-Westfalen"}, {"", ""}, {"42653", "42653"}, {"Solingen", "Solingen"},<BR /> {"Klosterhof 4", "Lützowstraße 347"}, {., 1.0767}, {., 965}, {}, {}, {0, 1},<BR /> ["gc#city" => {"Solingen", ., ., ., ., ., ., ., ., "Solingen"},
"gc#coordtype" => {"Point of Interest", "Waypoint", "Waypoint", "Waypoint", "Waypoint", "Waypoint", "Waypoint", "Waypoint", "Waypoint", "lPoint of Interest"},
"gc#ctrycd" => {"DE", ., ., ., ., ., ., ., ., "DE"},
"gc#dist" => {., 0.0064, 0.0499, 0.1481, 0.0853, 0.2366, 0.2993, 0.2478, 0.0032, 1.0767},<BR />"gc#district" => {"", ., ., ., ., ., ., ., ., ""},
"gc#lat" => {51.20971, 51.2099, 51.209949, 51.210171, 51.209187, 51.209667, 51.210789, 51.212135,51.213226, 51.21327},
"gc#leg" => {0, 1, 1, 1, 1, 1, 1, 1, 1},
"gc#long" => {7.07255, 7.072152, 7.072176, 7.072798, 7.074032, 7.074655, 7.077532, 7.081177, 7.084009, 7.08376},
"gc#msg" => {"", ., ., ., ., ., ., ., .},
"gc#postalc" => {"42653", ., ., ., ., ., ., ., ., "42653"},
"gc#ql" => {"exact", ., ., ., ., ., ., ., ., "exact"},
"gc#resp" => {0, ., ., ., ., ., ., ., .},
"gc#state" => {"Nordrhein-Westfalen", ., ., ., ., ., ., ., ., "Nordrhein-Westfalen"},<BR />"gc#street" => {"Klosterhof 4", "Klosterhof", ., "Gerberstraße", ., "Gräfrather Heide", .,<BR /> "Gräfrather Heide", "Lützowstraße", "Lützowstraße 347"},
"gc#time" => {., "00:00:05", "00:00:45", "00:02:13", "00:01:17", "00:03:32", "00:04:28", "00:03:42", "00:00:03", "00:16:05"},
"gc#wpidx" => {0, 1, 2, 3, 4, 5, 6, 7, 8, 0}], }
为简单起见,此示例使用两个彼此靠近的位置之间的路由。该路线由起点和终点之间的八个航路点组成。在关联数组的最后一个列表中使用键“ gc#wpidx”枚举它们。有些信息仅适用于开始和结束位置,这就是为什么某些列表缺少这么多值的原因。每个列表具有相同数量的元素,因此整个数组可以轻松转换为数据表。
技术细节
该函数将一对地址或地址列表作为输入。MapQuest发送回有关每个旅程的终点,每个位置的坐标,它们之间每个点的方向以及必须进行方向更改的位置的地理信息。对于这个简单的任务,MapQuest提供了不同的输入格式。地址信息可以作为一个文本字符串提供,并用逗号分隔,例如“ Deutschland,Schloßplatz2,42659 Solingen”,这是我家乡附近一座著名城堡的地址。或者,可以将地址指定为单个元素:country =“ Deutschland”,Street =“Schloßplatz2”,city =“ Solingen”,邮政编码=“ 42659”。
我认为在大多数情况下,将查找多个地址。因此,该函数希望以列表形式获取地址信息,或者是具有完整地址的字符串列表,或者是具有地址元素的多个列表。每个地址,无论其格式如何,都需要提供其国家/地区。并且没有检查是否提供了所需的最少信息。所有其他元素都是可选的。
如果请求详细的路由,则返回具有很多列表的数组。每个列表的第一个元素属于第一个位置,路径的后续元素,然后是第二个位置的一个元素,依此类推。为了区分输入到请求中的位置和返回的路由点,gc#coordtype将原始位置命名为“兴趣点”,并将其命名为“ Waypoints”之间的点。gc#leg列表将所有指向目的地的点粘合在一起。第一个位置不属于一条腿(我的定义)。对于到达并包括第一个目的地的路线,它是一个;到第二个目的地的路线是两个,依此类推。
如果为参数2提供了参考数据表的JSL变量,并且请求了详细的路由,则假定位置列表与数据表中的位置列表相同。被引用的数据表的所有内容将被复制,并通过详细的路由插入到阵列中。此信息只能链接到兴趣点,因为所有列表的航路点均缺少值。
如果找不到路线,则会在与该路线的原点相对应的位置给出错误消息。如果可能,将计算后续路线。
如果您提供指向数据表的链接,并且该数据表包含排除的行,则必须提供排除的行的列表(
excludedrows = As List( dt << Get Excluded Rows )
);作为参数12。否则,列表将不同步。在消息列表中,这些观察结果被标记为“已排除”。如果数据表中的“排除”观察值比原始观察值多,则这些观察值无法提供最少的位置信息。
我希望这段代码可以对您的项目有所帮助,或者只是提供一些JSL应用程序的见识。我欢迎任何问题或建议,但由于它是Geocoding 2020外接程序的一部分,因此我将仅进行与其在该外接程序中的预期用途一致的更改。