在Mathematica中处理KMZ

4
我是一名有用的助手,可以为您进行文本翻译。以下是需要翻译的内容:

我卡在一个转换上了。

我有一个带有一些坐标的KMZ文件。我像这样读取文件:

m=Import["~/Desktop/locations.kmz","Data"]

我得到了类似这样的东西:


{{LayerName->Point Features,
  Geometry->{
    Point[{-120.934,49.3321,372}],
    Point[{-120.935,49.3275,375}],
    Point[{-120.935,49.323,371}]},
  Labels->{},LabeledData->{},ExtendedData->{},
  PlacemarkNames->{1,2,3},
  Overlays->{},NetworkLinks->{}
}}

我希望能够从每个点中提取{x,y,z}以及与点相关联的标记名称{1,2,3}。即使我只能从Geometry -> {}中获取这些点,那也没关系,因为我可以使用List@@@将它们提取到列表中,但是我在基本部分迷失了方向,无法提取Geometry“Rule”。
感谢您的任何帮助,
罗恩

1
Ron,请您更新您的回答,显示从“Import”获取的实际数据。 显然它应该包含字符串。 - Mr.Wizard
4个回答

5

虽然Leonid的答案是正确的,但你可能会发现它在你的代码中不起作用。原因是你的Import命令输出的内容包含字符串,例如"LayerNames",而不是符号,例如LayerNames。我已经将一个KML文件上传到我的网站空间,这样我们就可以使用实际的Import命令来尝试一下。试试以下方法:

in = Import["http://facstaff.unca.edu/mcmcclur/my.kml", "Data"];
pointList = "Geometry" /.  
    Cases[in, Verbatim[Rule]["Geometry", _], Infinity];
pointList /. Point[stuff_] -> stuff

请注意,"Geometry"是一个字符串。事实上,in的内容如下所示(在InputForm中):
{{"LayerName" -> "Waypoints", 
  "Geometry" -> {Point[{-82.5, 32.5, 0}]}, 
  "Labels" -> {}, "LabeledData" -> {}, 
  "ExtendedData" -> {}, "PlacemarkNames" -> {"asheville"}, 
  "Overlays" -> {}, "NetworkLinks" -> {}}}

背景:KML指的是Keyhole标记语言。Keyhole是一家开发工具公司,后来被Google收购并最终成为了Google Earth。KMZ是KML的压缩版本。


哇塞,伙计们,感谢你们立即着手处理这个问题。我非常感激这个团队的反应迅速,特别是对于我的一些基础问题。 - Ron
马克,我的简化建议正确吗?我的逻辑是,"Geometry" /. ... 将返回找到的第一个 "Geometry" -> ... 规则的值,因此假设在 in 中存在这样的规则,则 Cases[..., 1] 应该是等效的。 - Mr.Wizard
@Mr.Wizard 您的代码运行良好。我已经添加了正确版本的导入KML文件,以便您可以尝试它。 - Mark McClure

4

我认为可以对Leonid和Mark的回答进行简化,安全地删除花哨的Verbatim结构。即:

Leonid的第一个操作可以写成:

Join @@ Cases[expr, (Geometry -> x_) :> (x /. Point -> Sequence), Infinity]

Leonid的第二次操作:


Join @@ Cases[expr, (PlacemarkNames -> x_) :> x, Infinity]

我在导入Mark的数据时遇到了麻烦,但据我猜测,可以这样写:

pointList = Cases[in, ("Geometry" -> x_) :> x, Infinity, 1]

我会根据这个答案的投票结果来判断自己是否正确。


@Mr.Wizard,你看到我在帖子底部的替代方法了吗?我认为它足够简单(尽管无关紧要,因为正如@Mark指出的那样,它不起作用。我基于OP的信息,不知道这些被返回为字符串)。 - Leonid Shifrin
谢谢Lenoid(和其他所有人),我使用了你们的一部分(用于地标)以及Mark的。现在我正在尝试简化版本,以了解它是如何工作的。 - Ron
@Leonid,是的,我做到了。我只是觉得值得指出的是(就我所知)Verbatim不是必需的。 - Mr.Wizard
@Mr.Wizard 我的意思是另外一件事 - 我们需要它来处理这种情况:Cases[{"Frog" -> 1, "Cat" -> 2, "Gerbil" -> 3}, (a_ :> b_)]会失败,我们需要在这里使用Verbatim - Leonid Shifrin
@Leonid,我会相信你的判断。那x:(_ -> _)呢? - Mr.Wizard
显示剩余6条评论

3

鉴于你的表达

expr = {{LayerName -> Point Features, 
       Geometry -> {
         Point[{-120.934, 49.3321, 372}], 
         Point[{-120.935, 49.3275, 375}],
         Point[{-120.935, 49.323, 371}]},
     Labels -> {}, LabeledData -> {}, ExtendedData -> {}, 
     PlacemarkNames -> {1, 2, 3}, Overlays -> {}, NetworkLinks -> {}}}

这将提取点:
In[121]:= 
   Flatten[Cases[expr, Verbatim[Rule][Geometry, x_] :> (x /. Point -> Sequence),
        Infinity], 1]

Out[121]= {{-120.934, 49.3321, 372}, {-120.935, 49.3275,375}, {-120.935, 49.323, 371}}

这将会提取地标:

In[124]:= Flatten[Cases[expr, Verbatim[Rule][PlacemarkNames, x_] :> x, Infinity], 1]

Out[124]= {1, 2, 3}

这里有一种更加优雅的方法,利用我们正在寻找规则的事实,将同时提取两者的规则:
In[127]:= 
{Geometry, PlacemarkNames} /.Cases[expr, _Rule, Infinity] /. Point -> Sequence

Out[127]= 
{{{-120.934, 49.3321, 372}, {-120.935, 49.3275,375}, {-120.935, 49.323, 371}}, {1, 2, 3}}

0

那么 Transpose[{"PlacemarkNames", "Geometry"} /. m[[1]]] 怎么样?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接