如何在谷歌上开设广告账户?打开谷歌广告需要哪些信息?

如何在Google上开通广告账户?开通Google ads(谷歌广告)需要什么资料?

首先我们了解一下Google谷歌广告的四大广告类型:(+:FXBR888)

搜索广告:搜索广告包括文字广告、自适应搜索广告、动态搜索广告以及来电专用广告(后面两种广告形 式入门教程不做介绍)。这些广告在搜索结果页上展示时,会带有“广告”标签;

展示位置:广告可以展示在 Google 搜索的搜索结果上方或下方,还可以展示在 Google Play、Google 购物、Google 图片和 Google 地图(包括 Google 地图应用)的搜索结果旁边、上方或下方。

展示广告:展示广告包括标准展示广告,智能展示广告以及 Gmail 广告;

展示位置:借助 Google 展示广告网络,无论用户是在浏览自己喜欢的网站、向朋友展示 YouTube 视频、查看 Gmail 帐号,还是在使用移动设备和应用,都可以向他们展示广告。

购物广告:购物广告包括标准购物广告、智能购物广告以及橱窗购物广告;

展示位置:广告可以展示在 Google 搜索上的“购物”标签(部分国家/地区)以及 Google 搜索(在搜索结果旁边并与文字广告分开)和 Google 图片。

视频广告:视频广告格式包括插播广告、视频发现广告、不可跳过的插播广告、外播广告和导视广告(入 门教程不做介绍);

展示位置:只能在 Youtube 上展示

-如何在Google上开通广告账户?

1、官网直接申请:https://ads.google.com(全程基本靠自己完成,对谷歌推广和广告账户操作有一定了解的用户可以尝试)

2、通过谷歌官方认证代理商申请Free!了解+V:FXBR888(目前谷歌在国内有授权多家公司为认证代理商,帮助国内用户开通谷歌企业账户,协助用户在谷歌上推广问题。)

-开通Google ads(谷歌广告)需要什么资料?

有Google账号即可申请开通Google ads;

划重点!!自己申请和通过代理商申请Google ads有什么区别?

1)自己开通的Google ads 账户容易因为付款方式导致可疑付款而被封户,解封是非常麻烦的!而代理商都是统一对公账户充值的,有官方认证的加持,不会出现可疑付款这种封户的原因!

2)如果是新手,自己开通Google ads账户后遇到操作问题难以得到解决,而代理商几乎都能提供比较全面的解答;

3)代理商跟Google官方都会保持比较密切的联系,针对优质的账户都会提供一些绿色通道,甚至还会有扶持政策,有机会跟官方直接面对面交流!

更多Google ads谷歌广告账户相关问题欢迎沟通交流+:FXBR888

谷歌广告系列和账户结构详细介绍(新手指南)

创建广告广告系列非常简单,只需几分钟即可完成。

但是,由于每一步都很应该谨慎对待

了解 Google Ads 谷歌广告的结构是开展广告的第一步。

因此,图帕先生决定写一篇详尽的谷歌广告系列和账号结构介绍,让大家了解下谷歌广告账号里面的内容,从而为今后的广告投放和优化方向捋清思路。

首先

为什么 Google 广告帐户结构如此重要?

拥有一个结构良好的帐户将:

  • 确保触发广告的搜索与你的受众群体相关。
  • 从而获得更好的质量得分,从而产生更好的结果和更低的价格。质量得分基本上是谷歌喜欢你的程度。
  • 让你井井有条,能够进一步优化。如果你的帐户一团糟,那么你可能会在混乱中迷失方向,你的结果会直线下降(或永远不会到达)。

帐户结构

以下是 PPC 帐户结构和内容的简单视图:

一个经理账号可以包含多个广告账号

每个广告帐户都会包含多个广告系列

每个广告系列都有多个广告组

广告组下建立多个广告

广告系列结构是 PPC 成功的最关键部分之一。有数百甚至数千种方法可以考虑构建你的广告系列。

其实和 Facebook 广告的账号层级非常类似:

下面介绍下每个层级的内容:

经理账号

为何要使用经理帐号

利用经理帐号,可以实现以下目标:

  • 使用单一登录信息访问所有 Google Ads 客户帐号,包括其他经理帐号。
  • 通过一个简明易懂的信息中心搜索、浏览和管理所有帐号。
  • 直接在经理帐号中为客户帐号创建和管理广告系列。
  • 轻松比较各个帐号的效果,一次性为多个帐号生成报告。
  • 使用合并结算,为所有客户帐号获取一份简洁的月度帐单。
  • 利用提醒,高效监控所有已关联帐号。
  • 在经理帐号中快速创建和关联 Google Ads 帐号。

资料来源:官方介绍

https://support.google.com/google-ads/answer/6139186?hl=zh-Hans

而使用经理账号最大的优势在于,可以进行月付账单!

这样就不用担心因为充值不及时,或者信用卡出问题而导致广告被停止投放。

账期是 30 天。

关于如何创建经理账号:

https://support.google.com/google-ads/answer/7459399?co=ADWORDS.IsAWNCustomer%3Dtrue&hl=zh-Hans

广告系列 Campaign

大致分为:

搜索广告

展示广告

购物广告

视频 YouTube 广告

App 广告

需要留意:

预算分配

由于 Google Ads 只有在广告系列 (Campaign Level) 才能操控每日预算上限,所以唯有广告活动架构的好,才能灵活组合操控预算分配。

举个例子,假设你是花商,你只用一个 Campaign (花),然后其下有许多 Ad Groups (玫瑰花、百合、太阳花…) 。

这个状况下,当你 Total Daily Budget 只有 100,你只能设定在 Campaign (花) 上面,然后让 Adwords 随机分配这 100 元到各个 Ad Group (玫瑰花、百合、向日葵…) 下。

广告预算只能在 Campaign Level 设定,无法准确掌控未来的广告群组花费这时候很有可能悲剧就会发生了,因为很有可能某一个 Ad Group (玫瑰花) 转换成效超好,但你的广告预算却被百合、向日葵、菊花..等其他 Ad Groups 通通吃掉。

如果有可能有上述状况者,应该考虑把 Ad Group (玫瑰花、百合、向日葵…),提高一个层级到 Campaign Level。

分开的广告活动,较能掌控预算分配

  • 有操纵多国广告的话,那同时还要思考针对各国不同的架构分配。

可设置部分

广告组

如修改广告组名称、出价等

广告和附加信息

查看该广告系列下所有广告

关键词

查看该广告系列下所有关键词

受众 Audience

只能在 Campaign 系列层面修改受众

人群 Demographic

针对不同年龄进行投放,可在广告组层面单独设置

设置 Setting

可在广告系列层面修改目标、投放网络、出价方式、预算等

地点 Location

可针对特定地点进行出价调整,比如针对加利佛尼亚州的用户提高 20%的出价

时间段 Ad Schedule

可针对特定时间进行出价调整,比如早上 9~12 点出价提高 20%,晚上凌晨 1~5 点降低 30%

设备 Device

可针对特定设备进行出价调整,比如移动端提高 20%出价

高级出价调整 Advanced bid adj.

可针对特定互动进行出价调整,比如致电出价提高 20%

改动历史 Change History

查看改动历史

草稿和测试 Draft&Experiment

设置广告的 A/B 测试

广告组 Ad Group

广告系列由一个或多个广告组组成。广告组只是:针对一组相关关键字的广告组。这有助于对相关关键字进行分组,并围绕共同主题撰写广告。

每个广告还包含你希望用户点击后访问的目标网页。

正如要制定广告系列结构一样,使用你要定位和排除的关键字制定广告组结构,多个版本的广告文案以及与关键字最相关的着陆页,这一点至关重要。

每个广告组都应与广告系列的目标相关联。

关键字应严格主题,然后广告文案应与广告组中的关键字密切相关,并正确反映这些搜索查询的意图。这对于获得高质量得分至关重要。

例如,销售几种不同类型鞋子的零售商不希望在同一广告组中使用“高跟鞋”和“跑鞋”。他们希望为每个产品编写不同的广告文案。而且他们希望那些寻找“高跟鞋”的人登上高跟鞋的页面和搜索“跑鞋”的人登陆他们提供的跑鞋页面。

可设置部分

广告和附加信息

查看该广告组下所有广告

关键词

查看该广告组下所有关键词

受众 Audience

查看广告系列层面下受众,需要在广告系列修改

人群 Demographic

针对不同年龄进行投放,可在单独设置

设置 Setting

可修改预算、广告轮播模式等

设备 Device

可针对特定设备进行出价调整,比如移动端提高 20%出价

改动历史 Change History

查看改动历史

广告

文字广告包含两个标题,说明,显示网址路径,目标网址和广告附加信息。

以下是谷歌 Ads 中的文字广告模板

广告制作

标题

每个标题最多可包含 30 个字符(包括空格)。它们显示在广告顶部的一行上。

这是广告中最突出的部分,也是抓住搜索者注意力的关键机会。

标题最好能够反映搜索意图,并将你产品和服务的优惠或功能透过文字展示出来。

描述

描述最长可达 90 个字符。

可以详细说明产品和服务的优势

显示路径 Display path

将会显示在搜索结果页,可以自定义 URL 路径的显示方式。域名是固定的。

可以在 URL 之后设置最多两个 15 个字符的路径。

例如,在你关于“女士牛仔裤 women’s jeans”的着陆页是:https://example.com/women-jeans-white-in-usa/

这里的路径可以设置成:/jeans 或者 /womens/jeans

让用户更清楚知道点击广告后,会去到什么样的页面。

最终网址 Final URL

这是用户点击广告后将要访问的目标网页,我们也叫着陆页。

确保着陆页与搜索查询相关,并提供良好的用户体验。

广告附加信息

广告附加信息可为你的广告提供更多信息, 有许多不同类型的广告扩展。

广告附加信息是根据上下文(例如设备和位置)以及预测的组合动态提供的,以提高点击率。

所有就算设置了,也不一定每次都会显示出来,谷歌会根据你广告的质量、排名、出价等因素动态调用。

位于第一位置的广告 – 排名靠前的广告 – 将有资格获得展示的更多广告附加信息。

以下是搜索“母亲节鲜花 mother’s day flowers”的示例。

除了 Title、Description、Display Path 外,其他都是广告附加信息

广告评级会确定广告附加信息是否会与您的广告一起展示。高度相关的扩展可以降低每次点击费用并提高页面排名。

因此,建议大家在广告中尽可能使用所有相关的广告附加信息。

如果未在广告系列中设置,Google 会动态生成一些附加信息,例如附加链接。

下面简单介绍下所有的附加信息类型:

附加链接Sitelink extensions

可链接到你网站上的其他网页。

广告可能会显示的附加链接数量在两到六个不等,而在可移动的轮播中最多可以在移动设备上显示八个。

卖点 Callout extensions

不可点击。它们旨在突出用户的优惠和利益。

示例包括“免费送货”,“免费退货”,和“退款保证”等。

可以在移动设备或桌面设备上随机显示两到六个标注。可以在帐户,广告系列或广告组一级设置它们。

结构化代码段 Structured snippet extension

不可点击。它们旨在突出你提供的产品或服务的各个方面。

结构化代码段扩展使用标题格式,如“课程 Courses”和“样式 Styles”等。

给一个例子:

如果你是服装零售商,可以设置成:Styles: Skinny, Straight, Flare, Jeggings

致电 Call extension

附加电话信息会在广告中附加电话号码。

在移动设备上,用户可以点按直接从分机拨打电话。

如果您没有设置附加电话信息,Google 可能会使用网站上的电话号码显示电话号码。

发送信息 Message extension

仅在能够发送和接收文本消息的移动设备上显示。

商家号码还必须能够发送和接收短信。

消息可以设置成“请用更多信息给我发短信 Please text me with more information”。

当有人点击广告中的邮件信息图标时,你就需要付费。而不是等到他们发送完信息后才收费。

位置 Location extension

如果你有真实的位置,则需要使用附加地址信息。

第一步是将“Google My Business”帐户与谷歌广告 Ads 帐户相关联。

附加地址信息可以在搜索和 Google 地图以及展示广告和视频广告中展示。

联盟商家 Affiliate location extension

在零售连锁店销售产品的品牌和制造商可以启用联盟附加地址信息,以帮助用户在附近的地点找到他们的产品。在美国,目前有超过 80 个连锁店可用于联盟会员附加地址。

价格Price extension

这些是可点击的扩展程序,可突出显示你提供的服务或产品的价格。

最多可以在移动设备上显示八个。

下面是一个示例,下拉菜单可以看到更多:

在此广告中,H&R Block 显示其服务菜单的价格。

每个价格扩展包括一个可自定义的标题和描述,每个最多 25 个字符。Google 建议至少设置五个价格扩展项。

应用程序App extension

这是可点击的链接,可让用户通过文字广告(Google 广告标题仍然访问网站)访问 Google Play 或 Apple App Store 中的移动应用程序。

注意

此附加信息不会替换 App 应用程序广告。

Google 会自动检测用户的设备类型,并仅在相应的设备上显示应用程序附加信息。

促销 Promotion extension

如果你有促销或优惠,促销信息可能是最好方法。

促销信息是可点击的,并带有价格标签图标,最多可包含两行文本。

在以下广告例子:

可以从下拉列表中选择一个特定节日,例如母亲节或黑色星期五。

也可以设置促销日期。

例如,黑色星期五促销活动仅在 10 月 15 日至 12 月 15 日期间展示。

小结

以上就是关于谷歌广告账号结构的全部内容,相信大家在开展广告之前先了解下账号结构,会对日后的广告投放工作起积极作用。

如果你有 Facebook 广告投放经验,相信你会很觉得谷歌账号结构其实没那么复杂。

如有问题,欢迎留言,我会尽量解答!

Peace Out!

关注图帕先生公众号yestupa,获取更多SEO、SEM干货

我的博客原文:

https://www.yestupa.com/google-ads-account-structure-guide.html

谷歌正试图在手机地图上显示交通信号灯

欢迎大家关注本头条号:

@Vic的数字化空间

定期推送最新最热的科技,

互联网,数字营销等相关资讯!


你或许很快就可以通过谷歌地图看到精确的交通灯情况了。

谷歌正在尝试一项新功能,即在地图中直接显示交通灯状况。根据Droid Life的报道,谷歌希望能够让用户在使用地图导航时,同时获取交通信号灯位置信息,以便让用户更加方便地规划路线。

就如下图:

但实际上,该功能目前只能显示某些地方有红绿灯,而并非实时切换红绿灯信号状况。如果未来真的有机会在电子地图上获取每个红绿灯实时状况,那就真的是一件让人无比兴奋的事了。

苹果去年在自己的地图中也推出了类似的功能。事实上,苹果在此功能上相较于谷歌还要更为先进一步,因为其中还包括了红灯信号数据。

事实上,Yandex地图在多年前已经具备了类似功能,甚至还要早于苹果地图。因此,从这个角度看,谷歌的这次尝试并不是什么重大创新。

而且就目前看来,谷歌地图的这项功能也还正处于实验阶段,Pixel手机用户还无法使用到该功能。但如果这项功获得了足够正面的用户反馈,它应该很快就会被加入到正式版本的谷歌地图应用程序中了。

我们还需继续关注。


欢迎大家关注本头条号:

@Vic的数字化空间

定期推送最新最热的科技,

互联网,数字营销等相关资讯!

解读空间信息和数字技术(大学排名)

空间信息与数字技术专业从2004年西安电子科技大学、武汉大学首先开设至今,经过了数年发展,已成为了一个比较成熟的专业。现在国内的空间信息与数字技术专业主要有两种内涵,一种是由武汉大学开创的(地理)空间信息与数字技术(即武大模式),另一种是西安电子科技大学开设的以外太空空间信息为研究对象的技术(即西电模式)。这两种方向虽然有相同的名字,学习的内容却相去甚远。以下将具体阐述。

GoogleMap武汉大学在2004年首创此专业,挂靠于国际软件学院。武汉大学拥有这亚洲最强、世界第三的测绘遥感专业,软件工程方面也是国内一流。武汉大学的空间信息与数字技术实际是遥感专业与软件工程专业的一个交叉学科。这里空间信息与数字技术实际应该称为(地理)空间信息与数字技术,这里看起来空间信息与数字技术是并列关系,实际上(地理)空间信息是处理对象,数字技术是处理方法。我们要做的就是使用计算机软件技术将巨量的空间信息转化为易被人接受形式的信息,并通过网络等手段将信息提供给客户(例如谷歌地图)。我们主要学习的是方法,因此实际上软件工程更接近这个专业。我们和软件工程所学内容的差别在于我们要掌握遥感的一般原理和方法,在课程上,我们只是多了空间信息导论、空间信息移动服务等几门专业课。也就是说,学习空间信息与数字技术,基本可以让你做软件工程能做的所有事,也能做他们不能干的事,实际上我们也是软件人才。2007年厦门理工学院开设的此专业,以及2009年山东农业大学开设此专业、成都理工大学2008年开始招生的这个专业都是按照武汉大学的模式教学,学习内容基本相同。

专业前景大概是所有人最关心的了,先说武大空信的前景。我们每届有大概80人,据老师说,每年被保送到各个名校读研的大概有30人,而考研到武大遥感院等各处的人应该也不少。国际软件学院的就业人中,年薪平均为6万,也不乏10万以上的人。可能有人要说我吹牛,这里我来给你分析一下。软件行业(其实空间信息与数字技术专业培养的也该算软件人才)最低收入一般月薪该有2500元(低等的程序员)而对于中等的软件设计师,月薪该有5000,即年薪60000.现在中国大学里培养的人才都是软件行业的中层人才,但由于现在中国软件人才培养结构不合理,中层人才过剩,底层和高层人才不足,很多高校培养的软件人才都必须干底层工作。事实上即使是国际软件学院这样的国家示范性软件学院,学生也大多要从底层做起。但示范性软件学院和国内很多大公司都有合作,国际软件学院和中软国际、东软集团等公司有长期合作,学生在大三、大四就可以进入大公司实习,优秀的学生有更多机会进入薪金水平较高的大公司。当然,也有四年没学到东西的同学,年薪60000是多个年薪30000与多个年薪100000甚至200000平均得到的。这里给你的是一个平台,发展的怎样还看你自己。

空间信息与数字技术专业就业薪酬统计

专业薪资区间占比

区间 2K-3K 3K-4.5K 4.5K-6K 6K-8K 8K-10K 10K-15K 15K-20K
占比 5.9% 25.2% 23.1% 18.5% 9.4% 8.8% 3.4%

通过2121份空间信息与数字技术专业就业状况分析,空间信息与数字技术专业平均薪酬水平为3191元。

你认为上面关于空间信息与数字技术专业的就业薪酬统计准确吗?太高还是太低了?

空间信息与数字技术专业就业排名统计

空间信息与数字技术专业就业前景怎么样?根据288份就业数据分析出:

在所有 1098个专业中,就业排名第691。

在工学170个专业中,就业排名第95。

在计算机类9个专业中,就业排名第9。

空间信息与数字技术专业就业区域和方向统计

空间信息与数字技术专业就业方向有哪些?哪个地区需求量比较大?根据288份就业数据分析出:

专业需求量最多的地区是“北京”,占28%

专业需求量最多的行业是“计算机软件”,占17%

除了上述就业地区和方向外,空间信息与数字技术专业在下面地区和方向中也特别受欢迎:

一、空间信息与数字技术专业就业方向分布

排名 方向 占比
1 计算机软件 17%
2 互联网/电子商务 14%
3 金融/投资/证券 10%
4 家具/家电/玩具/礼品 9%
5 快速消费品 9%
6 服装/纺织/皮革 9%
7 电子技术/半导体/集成电路 9%
8 计算机服务 9%
9 新能源 4%
10 网络游戏 4%

二、空间信息与数字技术专业就业地区分布

排名 地区 占比
1 北京 28%
2 深圳 25%
3 广州 12%
4 上海 8%
5 朝阳 7%
6 武汉 5%
7 沈阳 3%
8 南京 2%
9 秦皇岛 2%
10 郑州 2%

以上关于空间信息与数字技术专业就业前景和就业方向的各项数据分析仅供参考。选择大学专业是人生的一次转折点,选择大学专业不仅要看本专业的就业前景,更要注意就读人数和自己的兴趣爱好,再好的专业,因为就读人数过多,也同样会导致就业困难;如若选择一个不喜欢的专业,不但影响你的后期学习,也会影响到就业选择。

2017-2018年空间信息与数字技术专业排名

本文来源于评价网《Www.Nseec.Cn》

排 序 学校名称 水 平 开此专业学校数
1 武汉大学 5★ 16
2 西安电子科技大学 4★ 16
3 电子科技大学 4★ 16
4 重庆邮电大学 3★ 16
5 山东农业大学 3★ 16
6 上海海洋大学 3★ 16
7 河南工业大学 3★ 16
8 成都理工大学 3★ 16

想提高你的空间想象力吗?来和小编一起做这九个练习

9个每日活动能提升你的空间智能

9 Everyday Activities to Increase Your Spatial Intelligence

建筑师设计并组织空间,可以说,没有空间,就没有建筑。因此空间智能对建筑师的重要性不言而喻。空间智能,是指准确感知视觉空间及周围一切事物,并且能把所感觉到的形象以图画的形式表现出来的能力。幸运的是,空间智能是可以通过训练习得并提升的,不是天生就注定的或通过父母遗传而获得的。练习的越多,进步也就越大。所以为何不让这训练变的有趣且简单,简单到甚至在日常生活中就能训练。本文就为大家介绍9项可以提高你的空间智能日常活动,从绘画到语言甚至是游戏。

Architects design and organize spaces; without space, there is no architecture. So it goes without saying, therefore, that spatial intelligence is of high importance to architects. Luckily for us, spatial intelligence is not something you’re inherently gifted at or just “born with,” it’s something that can be trained and improved through practice. More practice means more advancement, so why not make it enjoyable and easy—easy enough even to do in your everyday life? From drawing to speaking to engaging in play, here are 9 everyday activities to improve your spatial intelligence.

1. 使用空间的词汇

研究表明让孩子多接触大量的空间词汇能增强他们的空间智能。在你的日常生活中尝试着使用更为精确的空间描述代替“这里”、“那里”,例如“橱柜顶端的右边”,或者“左起第三个盒子后面”。既便于像他人描述,你又会自发地想象空间。一个句子的基本构成就能提高你的空间智能。

1. Using Spatial Vocabulary

Some studies indicate that exposing children to a wide variety of spatial vocabulary increases their spatial intelligence.[1] Instead of using “here” or “there” in your everyday language, try being more specific in your spatial descriptions, such as “on the top shelf of the cupboard to the right,” or “the third to the left behind the box”. It will make you visualize the spaces yourself in order to describe it to others, an essential component to increasing your spatial intelligence.

2. 下棋

下棋时提前想好接下来的几步棋,总是个不错的策略。但是要做到这个,你必须在不移动任何棋子的情况下,想象后面每一步,不断变化的棋盘排列。在脑海里同时形成并记忆多个空间组合需要大量的联系,但也是在要比较多个选择时所需要的技能。

3. 玩乐高积木

提到“空间探索”,你或许也会联想到乐高积木。没有比手里拿着乐高的模块零件然后想出具有创意的拼接方式更有趣的游戏了。如今,如果你想到一个足够有趣的乐高拼接组合,可以大量投入生产,让其他人来自我挑战。

2. Playing Chess

Thinking a few steps ahead is always a good strategy when playing chess. However, in order to do this, you must visualize the changing composition of the board, step by step, without moving a single chess piece. Generating and retaining multiple spatial combinations in your mind at once takes a lot of practice, but is a great skill when needing to compare several options.

3. Playing with LEGO

Think “spatial exploration” and you’ll probably also think “LEGO.” No fun activity is more spatially educational than actually holding modular elements in your hands and coming up with creative ways of putting them together. These days, if you come up with a spatial combination that is interesting enough, it could even be put into production for others to spatially challenge themselves.

4. 使用记忆宫殿

很多人主张空间和记忆在本质上是相关联的,记忆宫殿显然支持这一说法。比如在心里走过一系列的空间,比如你的公寓,你把物体、数字、名字和一连串的东西和个人空间联系在一起。记忆可以变得很有趣从背电话号码到购物清单,而且这能帮你恢复空间的习得知识。

5. 玩电子游戏

空间智能最基本的训练就是在电子或电脑游戏里辨明方向。最近更有一个专门来测试空间感知的游戏。既然我们对建筑的体系如此有兴趣,何不尝试一下乐高积木的线上虚拟版,比如Minecraft? 那些游戏的积极份子早就完成了一长串的Minecraft里的建筑奇迹,在游戏的世界里,你能不受物理法则限制的,去定义和改变属于你的空降造物。

4. Use Memory Palaces

Many people argue that space and memory are essentially connected, and memory palaces certainly support that argument. By mentally walking through a series of spaces, such as the rooms in your apartment, you link objects, numbers, names or any list of things you need to remember to the individual spaces. It’s a fun way to remember anything from phone numbers to today’s grocery list, and it trains you to retrieve and recount spatial knowledge.

5. Play Video Games

Navigating through a video or computer game is often used as one of the primary examples of how to train one’s spatial intelligence. One recently released game was even designed specifically to test spatial perception; or, seeing as we are specifically interested in the discipline of architecture, why not try a virtual parallel to LEGO, such Minecraft? Active members already have a long list of Minecraft spatial wonders, but the unrestricted world allows you to experiment beyond our rules of physics to define and transform your own spatial creations.

6. 遥控无人机

如果你厌倦了坐在电脑前玩游戏,控制一架无人驾驶飞机是一个完美的替代方式。只使用几个操纵杆就能控制一个飞行物体通过空间,可比它听起来难的多。无人机的飞行方向在不断变化,迫使你要同时引导和跟踪无人机的旋转以正确定位它。它是需要你实时进行空间预判。

7. 创建你的城市认知地图

使用谷歌地图和其他 GPS 系统是很轻松容易的,频繁使用它们限制了我们创建自己的认知地图的能力。试着克制住下次用app来规划路线冲动,而去用你对于城市或当地的了解来构建路线。

8. 决难题

或者,如果你离不开你的手机,尝试下载能提高你对空间的推理,锻炼大脑的app,如Lumosity。如果你不使用手机,把手机换成别的东西一段时间,试着解决一个魔方。谜题,现实或虚拟的都是对空间智能极好的训练。

6. Fly a Drone

If you’re tired of sitting in front of a computer, flying a drone is a perfect alternative to playing a video game. Steering a flying object through space with just the use of a few joysticks is harder than it sounds. The direction in which the drone is flying is constantly changing, forcing one to simultaneously steer and track the drone’s rotation in order to correctly orient it. It’s a mental rotation test in real time.

7. Create a Mental Map of Your City

Google Maps and other GPS systems that are so easily accessibly on-the-go have limited our abilities to create our own mental maps. Try resisting the urge to plan your route through an app the next time you have an outing, and use your own knowledge of your city or local area to construct your own routes.

8. Solve Puzzles

Alternatively, if you can’t stay away from your phone, try downloading brain testing apps that are designed to improve your spatial reasoning, such as Lumosity. If you can get your hands away from your phone and replaced with something else for a while, try solving a Rubik’s Cube. Puzzles, both physical and virtual, can be excellent training for your spatial intelligence.

9. 速写

最后,作为一个建筑师当然离不开速写和手绘。我们喜欢涂鸦,何不从中学点什么?试着从各种角度、透视画一个几何体的三视图。可以画一个让朋友来解开的复杂迷宫,比如你公寓的空间记忆平面图。练得越多做得越好,贵在坚持。所以乐在其中很重要。

图片:Ariana Zilliacus

9. Sketching

Finally, as architects, we cannot leave out sketching. We all love doodling, so why not get some learning out of it? Try drawing three-dimensional geometry from a variety of angles, perspective exercises, funky mazes for your friends to solve, a memorized plan of your own apartment, or imaginary spaces. The more you practice, the better you become, but consistency is key. That’s why is so important that you have fun doing it.

参考:

Dewar, Gwen. “Spatial Intelligence in Children: Why Training Matters,” 2011-2016.

Lohman, David F. “Spatial Ability and G,” July 8, 1993.

由专筑网严越,韩平编译

【专筑网版权与免责声明】:本网站注明“来源:专筑网”的所有内容版权属专筑网所有,如需转载,请注明出处

高效的多维空间点索引算法——geohash和Googl

引子

每天我们晚上加班回家,可能都会用到滴滴或者共享单车。打开 app 会看到如下的界面:

app 界面上会显示出自己附近一个范围内可用的出租车或者共享单车。假设地图上会显示以自己为圆心,5公里为半径,这个范围内的车。如何实现呢?最直观的想法就是去数据库里面查表,计算并查询车距离用户小于等于5公里的,筛选出来,把数据返回给客户端。

这种做法比较笨,一般也不会这么做。为什么呢?因为这种做法需要对整个表里面的每一项都计算一次相对距离。太耗时了。既然数据量太大,我们就需要分而治之。那么就会想到把地图分块。这样即使每一块里面的每条数据都计算一次相对距离,也比之前全表都计算一次要快很多。

我们也都知道,现在用的比较多的数据库 MySQL、PostgreSQL 都原生支持 B+ 树。这种数据结构能高效的查询。地图分块的过程其实就是一种添加索引的过程,如果能想到一个办法,把地图上的点添加一个合适的索引,并且能够排序,那么就可以利用类似二分查找的方法进行快速查询。

问题就来了,地图上的点是二维的,有经度和纬度,这如何索引呢?如果只针对其中的一个维度,经度或者纬度进行搜索,那搜出来一遍以后还要进行二次搜索。那要是更高维度呢?三维。可能有人会说可以设置维度的优先级,比如拼接一个联合键,那在三维空间中,x,y,z 谁的优先级高呢?设置优先级好像并不是很合理。

本篇文章就来介绍2种比较通用的空间点索引算法。

一. GeoHash 算法

1. Genhash 算法简介

Genhash 是一种地理编码,由 Gustavo Niemeyer 发明的。它是一种分级的数据结构,把空间划分为网格。Genhash 属于空间填充曲线中的 Z 阶曲线(Z-order curve)的实际应用。

何为 Z 阶曲线?

上图就是 Z 阶曲线。这个曲线比较简单,生成它也比较容易,只需要把每个 Z 首尾相连即可。

Z 阶曲线同样可以扩展到三维空间。只要 Z 形状足够小并且足够密,也能填满整个三维空间。

说到这里可能读者依旧一头雾水,不知道 Geohash 和 Z 曲线究竟有啥关系?其实 Geohash算法 的理论基础就是基于 Z 曲线的生成原理。继续说回 Geohash。

Geohash 能够提供任意精度的分段级别。一般分级从 1-12 级。

字符串长度 cell 宽度 cell 高度

字符串长度 cell 宽度 cell 高度
1 5,000km × 5,000km
2 1,250km × 625km
3 156km × 156km
4 39.1km × 19.5km
5 4.89km × 4.89km
6 1.22km × 0.61km
7 153m × 153m
8 38.2m × 19.1m
9 4.77m × 4.77m
10 1.19m × 0.596m
11 149mm × 149mm
12 37.2mm × 18.6mm

还记得引语里面提到的问题么?这里我们就可以用 Geohash 来解决这个问题。

我们可以利用 Geohash 的字符串长短来决定要划分区域的大小。这个对应关系可以参考上面表格里面 cell 的宽和高。一旦选定 cell 的宽和高,那么 Geohash 字符串的长度就确定下来了。这样我们就把地图分成了一个个的矩形区域了。

地图上虽然把区域划分好了,但是还有一个问题没有解决,那就是如何快速的查找一个点附近邻近的点和区域呢?

Geohash 有一个和 Z 阶曲线相关的性质,那就是一个点附近的地方(但不绝对) hash 字符串总是有公共前缀,并且公共前缀的长度越长,这两个点距离越近。

由于这个特性,Geohash 就常常被用来作为唯一标识符。用在数据库里面可用 Geohash 来表示一个点。Geohash 这个公共前缀的特性就可以用来快速的进行邻近点的搜索。越接近的点通常和目标点的 Geohash 字符串公共前缀越长(但是这不一定,也有特殊情况,下面举例会说明)

Geohash 也有几种编码形式,常见的有2种,base 32 和 base 36。

Decimal 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Base 32 0 1 2 3 4 5 6 7 8 9 b c d e f g
Decimal 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Base 32 h j k m n p q r s t u v w x y z

base 36 的版本对大小写敏感,用了36个字符,“23456789bBCdDFgGhHjJKlLMnNPqQrRtTVWX”。

Decimal 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
Base 36 2 3 4 5 6 7 8 9 b B C d D F g G h H j
Decimal 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
Base 36 J K I L M n N P q Q r R t T V W X

2. Geohash 实际应用举例

接下来的举例以 base-32 为例。举个例子。

上图是一个地图,地图中间有一个美罗城,假设需要查询距离美罗城最近的餐馆,该如何查询?

第一步我们需要把地图网格化,利用 geohash。通过查表,我们选取字符串长度为6的矩形来网格化这张地图。

经过查询,美罗城的经纬度是[31.1932993, 121.43960190000007]。

先处理纬度。地球的纬度区间是[-90,90]。把这个区间分为2部分,即[-90,0),[0,90]。31.1932993位于(0,90]区间,即右区间,标记为1。然后继续把(0,90]区间二分,分为[0,45),[45,90],31.1932993位于[0,45)区间,即右左区间,标记为0。一直划分下去。

左区间 中值 右区间 二进制结果
-90 0 90 1
0 45 90 0
0 22.5 45 1
22.5 33.75 45 0
22.5 28.125 33.75 1
28.125 30.9375 33.75 1
30.9375 32.34375 33.75 0
30.9375 31.640625 32.34375 0
30.9375 31.2890625 31.640625 0
30.9375 31.1132812 31.2890625 1
31.1132812 31.2011718 31.2890625 0
31.1132812 31.1572265 31.2011718 1
31.1572265 31.1791992 31.2011718 1
31.1791992 31.1901855 31.2011718 1
31.1901855 31.1956786 31.2011718 0

再处理经度,一样的处理方式。地球经度区间是[-180,180]

左区间 中值 右区间 二进制结果
-180 0 180 1
0 90 180 1
90 135 180 0
90 112.5 135 1
112.5 123.75 135 0
112.5 118.125 123.75 1
118.125 120.9375 123.75 1
120.9375 122.34375 123.75 0
120.9375 121.640625 122.34375 0
120.9375 121.289062 121.640625 1
121.289062 121.464844 121.640625 0
121.289062 121.376953 121.464844 1
121.376953 121.420898 121.464844 1
121.420898 121.442871 121.464844 0
121.420898 121.431885 121.442871 1

纬度产生的二进制是101011000101110,经度产生的二进制是110101100101101,按照“偶数位放经度,奇数位放纬度”的规则,重新组合经度和纬度的二进制串,生成新的:111001100111100000110011110110,最后一步就是把这个最终的字符串转换成字符,对应需要查找 base-32 的表。11100 11001 11100 00011 00111 10110转换成十进制是 28 25 28 3 7 22,查表编码得到最终结果,wtw37q。

我们还可以把这个网格周围8个各自都计算出来。

从地图上可以看出,这邻近的9个格子,前缀都完全一致。都是wtw37。

如果我们把字符串再增加一位,会有什么样的结果呢?Geohash 增加到7位。

当Geohash 增加到7位的时候,网格更小了,美罗城的 Geohash 变成了 wtw37qt。

看到这里,读者应该已经清楚了 Geohash 的算法原理了。咱们把6位和7位都组合到一张图上面来看。

可以看到中间大格子的 Geohash 的值是 wtw37q,那么它里面的所有小格子前缀都是 wtw37q。可以想象,当 Geohash 字符串长度为5的时候,Geohash 肯定就为 wtw37 了。

接下来解释之前说的 Geohash 和 Z 阶曲线的关系。回顾最后一步合并经纬度字符串的规则,“偶数位放经度,奇数位放纬度”。读者一定有点好奇,这个规则哪里来的?凭空瞎想的?其实并不是,这个规则就是 Z 阶曲线。看下图:

x 轴就是纬度,y轴就是经度。经度放偶数位,纬度放奇数位就是这样而来的。

最后有一个精度的问题,下面的表格数据一部分来自 Wikipedia。

Geohash 字符串长度 纬度 经度 纬度误差 经度误差 km误差

Geohash 字符串长度 纬度 经度 纬度误差 经度误差 km误差
1 2 3 ±23 ±23 ±2500
2 5 5 ±2.8 ±5.6 ±630
3 7 8 ±0.70 ±0.70 ±78
4 10 10 ±0.087 ±0.18 ±20
5 12 13 ±0.022 ±0.022 ±2.4
6 15 15 ±0.0027 ±0.0055 ±0.61
7 17 18 ±0.00068 ±0.00068 ±0.076
8 20 20 ±0.000085 ±0.00017 ±0.019
9 22 23
10 25 25
11 27 28
12 30 30

3. Geohash 具体实现

到此,读者应该对 Geohash 的算法都很明了了。接下来用 Go 实现一下 Geohash 算法。

package geohashimport ( "bytes")const ( BASE32 = "0123456789bcdefghjkmnpqrstuvwxyz" MAX_LATITUDE float64 = 90 MIN_LATITUDE float64 = -90 MAX_LONGITUDE float64 = 180 MIN_LONGITUDE float64 = -180)var ( bits = []int{16, 8, 4, 2, 1} base32 = []byte(BASE32))type Box struct { MinLat, MaxLat float64 // 纬度 MinLng, MaxLng float64 // 经度}func (this *Box) Width() float64 { return this.MaxLng - this.MinLng}func (this *Box) Height() float64 { return this.MaxLat - this.MinLat}// 输入值:纬度,经度,精度(geohash的长度)// 返回geohash, 以及该点所在的区域func Encode(latitude, longitude float64, precision int) (string, *Box) { var geohash bytes.Buffer var minLat, maxLat float64 = MIN_LATITUDE, MAX_LATITUDE var minLng, maxLng float64 = MIN_LONGITUDE, MAX_LONGITUDE var mid float64 = 0 bit, ch, length, isEven := 0, 0, 0, true for length < precision { if isEven { if mid = (minLng + maxLng) / 2; mid < longitude { ch |= bits[bit] minLng = mid } else { maxLng = mid } } else { if mid = (minLat + maxLat) / 2; mid < latitude { ch |= bits[bit] minLat = mid } else { maxLat = mid } } isEven = !isEven if bit < 4 { bit++ } else { geohash.WriteByte(base32[ch]) length, bit, ch = length+1, 0, 0 } } b := &Box{ MinLat: minLat, MaxLat: maxLat, MinLng: minLng, MaxLng: maxLng, } return geohash.String(), b}

4. Geohash 的优缺点

Geohash 的优点很明显,它利用 Z 阶曲线进行编码。而 Z 阶曲线可以将二维或者多维空间里的所有点都转换成一维曲线。在数学上成为分形维。并且 Z 阶曲线还具有局部保序性。

Z 阶曲线通过交织点的坐标值的二进制表示来简单地计算多维度中的点的z值。一旦将数据被加到该排序中,任何一维数据结构,例如二叉搜索树,B树,跳跃表或(具有低有效位被截断)哈希表 都可以用来处理数据。通过 Z 阶曲线所得到的顺序可以等同地被描述为从四叉树的深度优先遍历得到的顺序。

这也是 Geohash 的另外一个优点,搜索查找邻近点比较快。

Geohash 的缺点之一也来自 Z 阶曲线。

Z 阶曲线有一个比较严重的问题,虽然有局部保序性,但是它也有突变性。在每个 Z 字母的拐角,都有可能出现顺序的突变。

看上图中标注出来的蓝色的点点。每两个点虽然是相邻的,但是距离相隔很远。看右下角的图,两个数值邻近红色的点两者距离几乎达到了整个正方形的边长。两个数值邻近绿色的点也达到了正方形的一半的长度。

Geohash 的另外一个缺点是,如果选择不好合适的网格大小,判断邻近点可能会比较麻烦。

看上图,如果选择 Geohash 字符串为6的话,就是蓝色的大格子。红星是美罗城,紫色的圆点是搜索出来的目标点。如果用 Geohash 算法查询的话,距离比较近的可能是 wtw37p,wtw37r,wtw37w,wtw37m。但是其实距离最近的点就在 wtw37q。如果选择这么大的网格,就需要再查找周围的8个格子。

如果选择 Geohash 字符串为7的话,那变成黄色的小格子。这样距离红星星最近的点就只有一个了。就是 wtw37qw。

如果网格大小,精度选择的不好,那么查询最近点还需要再次查询周围8个点。

二. 空间填充曲线 和 分形

在介绍第二种多维空间点索引算法之前,要先谈谈空间填充曲线(Space-filling curve)和分形。

解决多维空间点索引需要解决2个问题,第一,如何把多维降为低维或者一维?第二,一维的曲线如何分形?

1. 空间填充曲线

在数学分析中,有这样一个难题:能否用一条无限长的线,穿过任意维度空间里面的所有点?

在1890年,Giuseppe Peano 发现了一条连续曲线,现在称为 Peano 曲线,它可以穿过单位正方形上的每个点。他的目的是构建一个可以从单位区间到单位正方形的连续映射。 Peano 受到 Georg Cantor 早期违反直觉的研究结果的启发,即单位区间中无限数量的点与任何有限维度流型(manifold)中无限数量的点,基数相同。 Peano 解决的问题实质就是,是否存在这样一个连续的映射,一条能填充满平面的曲线。上图就是他找到的一条曲线。

一般来说,一维的东西是不可能填满2维的方格的。但是皮亚诺曲线恰恰给出了反例。皮亚诺曲线是一条连续的但处处不可导的曲线。

皮亚诺曲线的构造方法如下:取一个正方形并且把它分出九个相等的小正方形,然后从左下角的正方形开始至右上角的正方形结束,依次把小正方形的中心用线段连接起来;下一步把每个小正方形分成九个相等的正方形,然后上述方式把其中中心连接起来……将这种操作手续无限进行下去,最终得到的极限情况的曲线就被称作皮亚诺曲线。

皮亚诺对区间[0,1]上的点和正方形上的点的映射作了详细的数学描述。实际上,正方形的这些点对于

,可找到两个连续函数 x = f(t) 和 y = g(t),使得 x 和 y 取属于单位正方形的每一个值。

一年后,即1891年,希尔伯特就作出了这条曲线,叫希尔伯特曲线(Hilbert curve)。

上图就是1-6阶的希尔伯特曲线。具体构造方式在下一章再说。

上图是希尔伯特曲线填充满3维空间。

之后还有很多变种的空间填充曲线,龙曲线(Dragon curve)、 高斯帕曲线(Gosper curve)、Koch曲线(Koch curve)、摩尔定律曲线(Moore curve)、谢尔宾斯基曲线(Sierpiński curve)、奥斯古德曲线(Osgood curve)。这些曲线和本文无关,就不详细介绍了。

在数学分析中,空间填充曲线是一个参数化的注入函数,它将单位区间映射到单位正方形,立方体,更广义的,n维超立方体等中的连续曲线,随着参数的增加,它可以任意接近单位立方体中的给定点。除了数学重要性之外,空间填充曲线也可用于降维,数学规划,稀疏多维数据库索引,电子学和生物学。空间填充曲线的现在被用在互联网地图中。

2. 分形

皮亚诺曲线的出现,说明了人们对维数的认识是有缺陷的,有必要重新考察维数的定义。这就是分形几何考虑的问题。在分形几何中,维数可以是分数叫做分维。

多维空间降维以后,如何分形,也是一个问题。分形的方式有很多种,这里有一个列表,可以查看如何分形,以及每个分形的分形维数,即豪斯多夫分形维(Hausdorff fractals dimension)和拓扑维数。这里就不细说分形的问题了,感兴趣的可以仔细阅读链接里面的内容。

接下来继续来说多维空间点索引算法,下面一个算法的理论基础来自希尔伯特曲线,先来仔细说说希尔伯特曲线。

三. Hilbert Curve 希尔伯特曲线

1. 希尔伯特曲线的定义

希尔伯特曲线一种能填充满一个平面正方形的分形曲线(空间填充曲线),由大卫·希尔伯特在1891年提出。

由于它能填满平面,它的豪斯多夫维是2。取它填充的正方形的边长为1,第n步的希尔伯特曲线的长度是2^n – 2^(-n)。

2. 希尔伯特曲线的构造方法

一阶的希尔伯特曲线,生成方法就是把正方形四等分,从其中一个子正方形的中心开始,依次穿线,穿过其余3个正方形的中心。

二阶的希尔伯特曲线,生成方法就是把之前每个子正方形继续四等分,每4个小的正方形先生成一阶希尔伯特曲线。然后把4个一阶的希尔伯特曲线首尾相连。

三阶的希尔伯特曲线,生成方法就是与二阶类似,先生成二阶希尔伯特曲线。然后把4个二阶的希尔伯特曲线首尾相连。

n阶的希尔伯特曲线的生成方法也是递归的,先生成n-1阶的希尔伯特曲线,然后把4个n-1阶的希尔伯特曲线首尾相连。

3. 为何要选希尔伯特曲线

看到这里可能就有读者有疑问了,这么多空间填充曲线,为何要选希尔伯特曲线?

因为希尔伯特曲线有非常好的特性。

(1) 降维

首先,作为空间填充曲线,希尔伯特曲线可以对多维空间有效的降维。

上图就是希尔伯特曲线在填满一个平面以后,把平面上的点都展开成一维的线了。

可能有人会有疑问,上图里面的希尔伯特曲线只穿了16个点,怎么能代表一个平面呢?

当然,当n趋近于无穷大的时候,n阶希尔伯特曲线就可以近似填满整个平面了。

(2) 稳定

当n阶希尔伯特曲线,n趋于无穷大的时候,曲线上的点的位置基本上趋于稳定。举个例子:

上图左边是希尔伯特曲线,右边是蛇形的曲线。当n趋于无穷大的时候,两者理论上都可以填满平面。但是为何希尔伯特曲线更加优秀呢?

在蛇形曲线上给定一个点,当n趋于无穷大的过程中,这个点在蛇形曲线上的位置是时刻变化的。

这就造成了点的相对位置始终不定。

再看看希尔伯特曲线,同样是一个点,在n趋于无穷大的情况下:

从上图可以看到,点的位置几乎没有怎么变化。所以希尔伯特曲线更加优秀。

(3) 连续

希尔伯特曲线是连续的,所以能保证一定可以填满空间。连续性是需要数学证明的。具体证明方法这里就不细说了,感兴趣的可以点文章末尾一篇关于希尔伯特曲线的论文,那里有连续性的证明。

接下来要介绍的谷歌的 S2 算法就是基于希尔伯特曲线的。现在读者应该明白选择希尔伯特曲线的原因了吧。

四. S? 算法

Google’s S2 library is a real treasure, not only due to its capabilities for spatial indexing but also because it is a library that was released more than 4 years ago and it didn’t get the attention it deserved

上面这段话来自2015年一位谷歌工程师的博文。他由衷的感叹 S2 算法发布4年没有得到它应有的赞赏。不过现在 S2 已经被各大公司使用了。

在介绍这个重量级算法之前,先解释一些这个算法的名字由来。S2其实是来自几何数学中的一个数学符号 S?,它表示的是单位球。S2 这个库其实是被设计用来解决球面上各种几何问题的。值得提的一点是,除去 golang 官方 repo 里面的 geo/s2 完成度目前只有40%,其他语言,Java,C++,Python 的 S2 实现都完成100%了。本篇文章讲解以 Go 的这个版本为主。

接下来就看看怎么用 S2 来解决多维空间点索引的问题的。

1. 球面坐标转换

按照之前我们处理多维空间的思路,先考虑如何降维,再考虑如何分形。

众所周知,地球是近似一个球体。球体是一个三维的,如何把三维降成一维呢?

球面上的一个点,在直角坐标系中,可以这样表示:

123x = r * sin θ * cos φy = r * sin θ * sin φ z = r * cos θ

通常地球上的点我们会用经纬度来表示。

再进一步,我们可以和球面上的经纬度联系起来。不过这里需要注意的是,纬度的角度 α 和直角坐标系下的球面坐标 θ 加起来等于 90°。所以三角函数要注意转换。

于是地球上任意的一个经纬度的点,就可以转换成 f(x,y,z)。

在 S2 中,地球半径被当成单位 1 了。所以半径不用考虑。x,y,z的值域都被限定在了[-1,1] x [-1,1] x [-1,1]这个区间之内了。

2. 球面变平面

接下来一步 S2 把球面碾成平面。怎么做的呢?

首先在地球外面套了一个外切的正方体,如下图。

从球心向外切正方体6个面分别投影。S2 是把球面上所有的点都投影到外切正方体的6个面上。

这里简单的画了一个投影图,上图左边的是投影到正方体一个面的示意图,实际上影响到的球面是右边那张图。

从侧面看,其中一个球面投影到正方体其中一个面上,边缘与圆心的连线相互之间的夹角为90°,但是和x,y,z轴的角度是45°。我们可以在球的6个方向上,把45°的辅助圆画出来,见下图左边。

上图左边的图画了6个辅助线,蓝线是前后一对,红线是左右一对,绿线是上下一对。分别都是45°的地方和圆心连线与球面相交的点的轨迹。这样我们就可以把投影到外切正方体6个面上的球面画出来,见上图右边。

投影到正方体以后,我们就可以把这个正方体展开了。

一个正方体的展开方式有很多种。不管怎么展开,最小单元都是一个正方形。

以上就是 S2 的投影方案。接下来讲讲其他的投影方案。

首先有下面一种方式,三角形和正方形组合。

这种方式展开图如下图。

这种方式其实很复杂,构成子图形由两种图形构成。坐标转换稍微复杂一点。

再还有一种方式是全部用三角形组成,这种方式三角形个数越多,就能越切近于球体。

上图最左边的图,由20个三角形构成,可以看的出来,菱角非常多,与球体相差比较大,当三角形个数越来越多,就越来越贴近球体。

20个三角形展开以后就可能变成这样。

最后一种方式可能是目前最好的方式,不过也可能是最复杂的方式。按照六边形来投影。

六边形的菱角比较少,六个边也能相互衔接其他的六边形。看上图最后边的图可以看出来,六边形足够多以后,非常近似球体。

六边形展开以后就是上面这样。当然这里只有12个六边形。六边形个数越多越好,粒度越细,就越贴近球体。

Uber 在一个公开分享上提到了他们用的是六边形的网格,把城市划分为很多六边形。这块应该是他们自己开发的。也许滴滴也是划分六边形,也许滴滴有更好的划分方案也说不定。

回到 S2 上面来,S2是用的正方形。这样第一步的球面坐标进一步的被转换成 f(x,y,z) -> g(face,u,v),face是正方形的六个面,u,v对应的是六个面中的一个面上的x,y坐标。

3. 球面矩形投影修正

上一步我们把球面上的球面矩形投影到正方形的某个面上,形成的形状类似于矩形,但是由于球面上角度的不同,最终会导致即使是投影到同一个面上,每个矩形的面积也不大相同。

上图就表示出了球面上个一个球面矩形投影到正方形一个面上的情况。

经过实际计算发现,最大的面积和最小的面积相差5.2倍。见上图左边。相同的弧度区间,在不同的纬度上投影到正方形上的面积不同。

现在就需要修正各个投影出来形状的面积。如何选取合适的映射修正函数就成了关键。目标是能达到上图右边的样子,让各个矩形的面积尽量相同。

这块转换的代码在 C++ 的版本里面才有详细的解释,在 Go 的版本里面只一笔带过了。害笔者懵逼了好久。

面积比率 边比率 对角线比率 ToPointRaw ToPoint FromPoint
线性变换 5.200 2.117 2.959 0.020 0.087 0.085
tan()变换 1.414 1.414 1.704 0.237 0.299 0.258
二次变换 2.082 1.802 1.932 0.033 0.096 0.108

线性变换是最快的变换,但是变换比最小。tan() 变换可以使每个投影以后的矩形的面积更加一致,最大和最小的矩形比例仅仅只差0.414。可以说非常接近了。但是 tan() 函数的调用时间非常长。如果把所有点都按照这种方式计算的话,性能将会降低3倍。

最后谷歌选择的是二次变换,这是一个近似切线的投影曲线。它的计算速度远远快于 tan() ,大概是 tan() 计算的3倍速度。生成的投影以后的矩形大小也类似。不过最大的矩形和最小的矩形相比依旧有2.082的比率。

上表中,ToPoint 和 FromPoint 分别是把单位向量转换到 Cell ID 所需要的毫秒数、把 Cell ID 转换回单位向量所需的毫秒数(Cell ID 就是投影到正方体六个面,某个面上矩形的 ID,矩形称为 Cell,它对应的 ID 称为 Cell ID)。ToPointRaw 是某种目的下,把 Cell ID 转换为非单位向量所需的毫秒数。

在 S2 中默认的转换是二次转换。

1#define S2_PROJECTION S2_QUADRATIC_PROJECTION

详细看看这三种转换到底是怎么转换的。

#if S2_PROJECTION == S2_LINEAR_PROJECTIONinline double S2::STtoUV(double s) { return 2 * s - 1;}inline double S2::UVtoST(double u) { return 0.5 * (u + 1);}#elif S2_PROJECTION == S2_TAN_PROJECTIONinline double S2::STtoUV(double s) { // Unfortunately, tan(M_PI_4) is slightly less than 1.0. This isn't due to // a flaw in the implementation of tan(), it's because the derivative of // tan(x) at x=pi/4 is 2, and it happens that the two adjacent floating // point numbers on either side of the infinite-precision value of pi/4 have // tangents that are slightly below and slightly above 1.0 when rounded to // the nearest double-precision result. s = tan(M_PI_2 * s - M_PI_4); return s + (1.0 / (GG_LONGLONG(1) << 53)) * s;}inline double S2::UVtoST(double u) { volatile double a = atan(u); return (2 * M_1_PI) * (a + M_PI_4);}#elif S2_PROJECTION == S2_QUADRATIC_PROJECTIONinline double S2::STtoUV(double s) { if (s >= 0.5) return (1/3.) * (4*s*s - 1); else return (1/3.) * (1 - 4*(1-s)*(1-s));}inline double S2::UVtoST(double u) { if (u >= 0) return 0.5 * sqrt(1 + 3*u); else return 1 - 0.5 * sqrt(1 - 3*u);}#else#error Unknown value for S2_PROJECTION#endif

上面有一处对 tan(M_PI_4) 的处理,是因为精度的原因,导致略小于1.0 。

所以投影之后的修正函数三种变换应该如下:

// 线性转换u = 0.5 * ( u + 1)// tan() 变换u = 2 / pi * (atan(u) + pi / 4) = 2 * atan(u) / pi + 0.5// 二次变换u >= 0,u = 0.5 * sqrt(1 + 3*u)u < 0, u = 1 - 0.5 * sqrt(1 - 3*u)

注意上面虽然变换公式只写了u,不代表只变换u。实际使用过程中,u,v都分别当做入参,都会进行变换。

这块修正函数在 Go 的版本里面就直接只实现了二次变换,其他两种变换方式找遍整个库,根本没有提及。

// stToUV converts an s or t value to the corresponding u or v value.// This is a non-linear transformation from [-1,1] to [-1,1] that// attempts to make the cell sizes more uniform.// This uses what the C++ version calls 'the quadratic transform'.func stToUV(s float64) float64 { if s >= 0.5 { return (1 / 3.) * (4*s*s - 1) } return (1 / 3.) * (1 - 4*(1-s)*(1-s))}// uvToST is the inverse of the stToUV transformation. Note that it// is not always true that uvToST(stToUV(x)) == x due to numerical// errors.func uvToST(u float64) float64 { if u >= 0 { return 0.5 * math.Sqrt(1+3*u) } return 1 - 0.5*math.Sqrt(1-3*u)}

经过修正变换以后,u,v都变换成了s,t。值域也发生了变化。u,v的值域是[-1,1],变换以后,是s,t的值域是[0,1]。

至此,小结一下,球面上的点S(lat,lng) -> f(x,y,z) -> g(face,u,v) -> h(face,s,t)。目前总共转换了4步,球面经纬度坐标转换成球面xyz坐标,再转换成外切正方体投影面上的坐标,最后变换成修正后的坐标。

到目前为止,S2 可以优化的点有两处,一是投影的形状能否换成六边形?二是修正的变换函数能否找到一个效果和 tan() 类似的函数,但是计算速度远远高于 tan(),以致于不会影响计算性能?

4. 点与坐标轴点相互转换

在 S2 算法中,默认划分 Cell 的等级是30,也就是说把一个正方形划分为 2^30 * 2^30个小的正方形。

那么上一步的s,t映射到这个正方形上面来,对应该如何转换呢?

s,t的值域是[0,1],现在值域要扩大到[0,230-1]。

// stToIJ converts value in ST coordinates to a value in IJ coordinates.func stToIJ(s float64) int { return clamp(int(math.Floor(maxSize*s)), 0, maxSize-1)}

C ++ 的实现版本也一样

inline int S2CellId::STtoIJ(double s) { // Converting from floating-point to integers via static_cast is very slow // on Intel processors because it requires changing the rounding mode. // Rounding to the nearest integer using FastIntRound() is much faster. // 这里减去0.5是为了四舍五入 return max(0, min(kMaxSize - 1, MathUtil::FastIntRound(kMaxSize * s - 0.5)));}

到这一步,是h(face,s,t) -> H(face,i,j)。

5. 坐标轴点与希尔伯特曲线 Cell ID 相互转换

最后一步,如何把 i,j 和希尔伯特曲线上的点关联起来呢?

const ( lookupBits = 4 swapMask = 0x01 invertMask = 0x02)var ( ijToPos = [4][4]int{ {0, 1, 3, 2}, // canonical order {0, 3, 1, 2}, // axes swapped {2, 3, 1, 0}, // bits inverted {2, 1, 3, 0}, // swapped & inverted } posToIJ = [4][4]int{ {0, 1, 3, 2}, // canonical order: (0,0), (0,1), (1,1), (1,0) {0, 2, 3, 1}, // axes swapped: (0,0), (1,0), (1,1), (0,1) {3, 2, 0, 1}, // bits inverted: (1,1), (1,0), (0,0), (0,1) {3, 1, 0, 2}, // swapped & inverted: (1,1), (0,1), (0,0), (1,0) } posToOrientation = [4]int{swapMask, 0, 0, invertMask | swapMask} lookupIJ [1 << (2*lookupBits + 2)]int lookupPos [1 << (2*lookupBits + 2)]int)

在变换之前,先来解释一下定义的一些变量。

posToIJ 代表的是一个矩阵,里面记录了一些单元希尔伯特曲线的位置信息。

把 posToIJ 数组里面的信息用图表示出来,如下图:

同理,把 ijToPos 数组里面的信息用图表示出来,如下图:

posToOrientation 数组里面装了4个数字,分别是1,0,0,3。

lookupIJ 和 lookupPos 分别是两个容量为1024的数组。这里面分别对应的就是希尔伯特曲线 ID 转换成坐标轴 IJ 的转换表,和坐标轴 IJ 转换成希尔伯特曲线 ID 的转换表。

func init() { initLookupCell(0, 0, 0, 0, 0, 0) initLookupCell(0, 0, 0, swapMask, 0, swapMask) initLookupCell(0, 0, 0, invertMask, 0, invertMask) initLookupCell(0, 0, 0, swapMask|invertMask, 0, swapMask|invertMask)}

这里是初始化的递归函数,在希尔伯特曲线的标准顺序中可以看到是有4个格子,并且格子都有顺序的,所以初始化要遍历满所有顺序。入参的第4个参数,就是从0 – 3 。

// initLookupCell initializes the lookupIJ table at init time.func initLookupCell(level, i, j, origOrientation, pos, orientation int) { if level == lookupBits { ij := (i << lookupBits) + j lookupPos[(ij<<2)+origOrientation] = (pos << 2) + orientation lookupIJ[(pos<<2)+origOrientation] = (ij << 2) + orientation return } level++ i <<= 1 j <<= 1 pos <>1), j+(r[0]&1), origOrientation, pos, orientation^posToOrientation[0]) initLookupCell(level, i+(r[1]>>1), j+(r[1]&1), origOrientation, pos+1, orientation^posToOrientation[1]) initLookupCell(level, i+(r[2]>>1), j+(r[2]&1), origOrientation, pos+2, orientation^posToOrientation[2]) initLookupCell(level, i+(r[3]>>1), j+(r[3]&1), origOrientation, pos+3, orientation^posToOrientation[3])}

上面这个函数是生成希尔伯特曲线的。我们可以看到有一处对pos << 2的操作,这里是把位置变换到第一个4个小格子中,所以位置乘以了4。

由于初始设置的lookupBits = 4,所以i,j的变化范围是从[0,15],总共有16*16=256个,然后i,j坐标是表示的4个格子,再细分,lookupBits = 4这种情况下能表示的点的个数就是256*4=1024个。这也正好是 lookupIJ 和 lookupPos 的总容量。

画一个局部的图,i,j从0-7变化。

上图是一个4阶希尔伯特曲线。初始化的实际过程就是初始化4阶希尔伯特上的1024个点的坐标与坐标轴上的x,y轴的对应关系表。

举个例子,下表是i,j在递归过程中产生的中间过程。下表是

lookupPos 表计算过程。

(i,j) ij ij 计算过程 lookupPos[i j] lookupPos[i j]计算过程 实际坐标
(0,0) 0 0 0 0 (0,0)
(1,0) 64 (1*16+0)*4=64 5 1*4+1=5 (3,0)
(1,1) 68 (1*16+1)*4=68 9 2*4+1=5 (3,2)
(0,1) 4 (0*16+1)*4=4 14 3*4+2=14 (0,2)
(0,2) 8 (0*16+2)*4=8 17 4*4+1=17 (1,4)
(0,3) 12 (0*16+3)*4=12 20 5*4+0=20 (0,6)
(1,3) 76 (1*16+3)*4=76 24 6*4+0=24 (2,6)
(1,2) 72 (1*16+2)*4=72 31 7*4+3=31 (3,4)
(2,2) 136 (2*16+2)*4=136 33 8*4+1=33 (5,4)

取出一行详细分析一下计算过程。

假设当前(i,j)=(0,2),ij 的计算过程是把 i 左移4位再加上 j,整体结果再左移2位。目的是为了留出2位的方向位置。ij的前4位是i,接着4位是j,最后2位是方向。这样计算出ij的值就是8 。

接着计算lookupPos[i j]的值。从上图中可以看到(0,2)代表的单元格的4个数字是16,17,18,19 。计算到这一步,pos的值为4(pos是专门记录生成格子到第几个了,总共pos的值会循环0-255)。pos代表的是当前是第几个格子(4个小格子组成),当前是第4个,每个格子里面有4个小格子。所以4*4就可以偏移到当前格子的第一个数字,也就是16 。posToIJ 数组里面会记录下当前格子的形状。从这里我们从中取出 orientation 。

看上图,16,17,18,19对应的是 posToIJ 数组轴旋转的情况,所以17是位于轴旋转图的数字1代表的格子中。这时 orientation = 1 。

这样 lookupPos[i j] 表示的数字就计算出来了,4*4+1=17 。这里就完成了i,j与希尔伯特曲线上数字的对应。

那如何由希尔伯特曲线上的数字对应到实际的坐标呢?

lookupIJ 数组里面记录了反向的信息。lookupIJ 数组 和 lookupPos 数组存储的信息正好是反向的。lookupIJ 数组 下表存的值是 lookupPos 数组 的下表。我们查 lookupIJ 数组 ,lookupIJ[17]的值就是8,对应算出来(i,j)=(0,2)。这个时候的i,j还是大格子。还是需要借助 posToIJ 数组 里面描述的形状信息。当前形状是轴旋转,之前也知道 orientation = 1,由于每个坐标里面有4个小格子,所以一个i,j代表的是2个小格子,所以需要乘以2,再加上形状信息里面的方向,可以计算出实际的坐标 (0 * 2 + 1 , 2 * 2 + 0) = ( 1,4) 。

至此,整个球面坐标的坐标映射就已经完成了。

球面上的点S(lat,lng) -> f(x,y,z) -> g(face,u,v) -> h(face,s,t) -> H(face,i,j) -> CellID。目前总共转换了6步,球面经纬度坐标转换成球面xyz坐标,再转换成外切正方体投影面上的坐标,最后变换成修正后的坐标,再坐标系变换,映射到 [0,230-1]区间,最后一步就是把坐标系上的点都映射到希尔伯特曲线上。

6. S2 Cell ID 数据结构

最后需要来谈谈 S2 Cell ID 数据结构,这个数据结构直接关系到不同 Level 对应精度的问题。

在 S2 中,每个 CellID 是由64位的组成的。可以用一个 uint64 存储。开头的3位表示正方体6个面中的一个,取值范围[0,5]。3位可以表示0-7,但是6,7是无效值。

64位的最后一位是1,这一位是特意留出来的。用来快速查找中间有多少位。从末尾最后一位向前查找,找到第一个不为0的位置,即找到第一个1。这一位的前一位到开头的第4位(因为前3位被占用)都是可用数字。

绿色格子有多少个就能表示划分多少格。上图左图,绿色的有60个格子,于是可以表示[0,230 -1] * [0,230 -1]这么多个格子。上图右图中,绿色格子只有36个,那么就只能表示[0,218 -1]*[0,218 -1]这么多个格子。

那么不同 level 可以代表的网格的面积究竟是多大呢?

由上一章我们知道,由于投影的原因,所以导致投影之后的面积依旧有大小差别。

这里推算的公式比较复杂,就不证明了,具体的可以看文档。

MinAreaMetric = Metric{2, 8 * math.Sqrt2 / 9} AvgAreaMetric = Metric{2, 4 * math.Pi / 6} MaxAreaMetric = Metric{2, 2.635799256963161491}

这就是最大最小面积和平均面积的倍数关系。

level 0 就是正方体的六个面之一。地球表面积约等于510,100,000 km2。level 0 的面积就是地球表面积的六分之一。level 30 能表示的最小的面积0.48cm2,最大也就0.93cm2 。

7. S2 与 Geohash 对比

Geohash 有12级,从5000km 到 3.7cm。中间每一级的变化比较大。有时候可能选择上一级会大很多,选择下一级又会小一些。比如选择字符串长度为4,它对应的 cell 宽度是39.1km,需求可能是50km,那么选择字符串长度为5,对应的 cell 宽度就变成了156km,瞬间又大了3倍了。这种情况选择多长的 Geohash 字符串就比较难选。选择不好,每次判断可能就还需要取出周围的8个格子再次进行判断。Geohash 需要 12 bytes 存储。

S2 有30级,从 0.7cm? 到 85,000,000km? 。中间每一级的变化都比较平缓,接近于4次方的曲线。所以选择精度不会出现 Geohash 选择困难的问题。S2 的存储只需要一个 uint64 即可存下。

S2 库里面不仅仅有地理编码,还有其他很多几何计算相关的库。地理编码只是其中的一小部分。本文没有介绍到的 S2 的实现还有很多很多,各种向量计算,面积计算,多边形覆盖,距离问题,球面球体上的问题,它都有实现。

S2 还能利用贪心算法求局部最优解。比如给定一个城市,求一个最优的解,多边形刚刚好覆盖住这个城市。

如上图,生成的多边形刚刚好覆盖住下面蓝色的区域。这里生成的多边形可以有大有小。不管怎么样,最终的结果也是刚刚覆盖住目标物。

用相同的 Cell 也可以达到相同的目的,上图就是用相同 Level 的 Cell 覆盖了整个圣保罗城市。

这些都是 Geohash 做不到的。

8. S2 Cell 举例

先来看看经纬度和 CellID 的转换,以及矩形面积的计算。

latlng := s2.LatLngFromDegrees(31.232135, 121.41321700000003) cellID := s2.CellIDFromLatLng(latlng) cell := s2.CellFromCellID(cellID) //9279882742634381312 // cell.Level() fmt.Println("latlng = ", latlng) fmt.Println("cell level = ", cellID.Level()) fmt.Printf("cell = %dn", cellID) smallCell := s2.CellFromCellID(cellID.Parent(10)) fmt.Printf("smallCell level = %dn", smallCell.Level()) fmt.Printf("smallCell id = %bn", smallCell.ID()) fmt.Printf("smallCell ApproxArea = %vn", smallCell.ApproxArea()) fmt.Printf("smallCell AverageArea = %vn", smallCell.AverageArea()) fmt.Printf("smallCell ExactArea = %vn", smallCell.ExactArea())

这里 Parent 方法参数可以直接指定返回改点的对应 level 的 CellID。

上面那些方法打印出来的结果如下:

latlng = [31.2321350, 121.4132170]cell level = 30cell = 3869277663051577529****Parent **** 10000000000000000000000000000000000000000smallCell level = 10smallCell id = 11010110110010011011110000000000000000000000000000000000000000smallCell ApproxArea = 1.9611002454714756e-06smallCell AverageArea = 1.997370817559429e-06smallCell ExactArea = 1.9611009480261058e-06

再举一个覆盖多边形的例子。我们先随便创建一个区域。

rect = s2.RectFromLatLng(s2.LatLngFromDegrees(48.99, 1.852)) rect = rect.AddPoint(s2.LatLngFromDegrees(48.68, 2.75)) rc := &s2.RegionCoverer{MaxLevel: 20, MaxCells: 10, MinLevel: 2} r := s2.Region(rect.CapBound()) covering := rc.Covering(r)

覆盖参数设置成 level 2 – 20,最多的 Cell 的个数是10个。

接着我们把 Cell 至多改成20个。

最后再改成30个。

可以看到相同的 level 的范围,cell 个数越多越精确目标范围。

这里是匹配矩形区域,匹配圆形区域也同理。

代码就不贴了,与矩形类似。这种功能 Geohash 就做不到,需要自己手动实现了。

9. S2 的应用

S2 目前应用比较多,用在和地图相关业务上更多。Google Map 就直接大量使用了 S2 ,速度有多快读者可以自己体验体验。Uber 在搜寻最近的出租车也是用的 S2 算法进行计算的。场景的例子就是本篇文章引语里面提到的场景。滴滴应该也有相关的应用,也许有更加优秀的解法。现在很火的共享单车也会用到这些空间索引算法。

最后就是外卖行业和地图关联也很密切。美团和饿了么相信也在这方面有很多应用,具体哪里用到了,就请读者自己想象吧。

五. 最后

本篇文章里面着重介绍了谷歌的 S2 算法的基础实现。虽然 Geohash 也是空间点索引算法,但是性能方面比谷歌的 S2 略逊一筹。并且大公司的数据库也基本上开始采用谷歌的 S2 算法进行索引。

关于空间搜索其实还有一大类问题,如何搜索多维空间线,多维空间面,多维空间多边形呢?他们都是由无数个空间点组成的。实际的例子,比如街道,高楼,铁路,河流。要搜索这些东西,数据库表如何设计?如何做到高效的搜索呢?还能用 B+ 树来做么?

答案当然是也可以实现高效率的搜索,那就需要用到 R 树,或者 R 树 和 B+树。

这部分就不在本文的范畴内了,下次有空可以再分享一篇《多维空间多边形索引算法》

最后,请大家多多指点。

  • 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

空间灵感|谷歌地图应用实现互动“蝙蝠洞”体验

当谷歌想要促进新蝙蝠侠vs超人电影的时候,华纳兄弟介绍团队去往。与谷歌和华纳兄弟密切合作,创建了一个交互式蝙蝠洞的经历可以只通过谷歌地图应用程序。使用摄影工作室的视效调查资产供应商,重新创建真正的蝙蝠洞高清细节将带到蝙蝠侠系列的粉丝们的生活。

回复 / 投稿 / 或加微信 / 619991688

天空下X设绘主意,推荐有梦想的人

地理智能企业Carto赢得了6100万美元的C轮融资,用于构建云本地空间分析平台

36氪获悉,位置智能企业「CARTO」获得6100万美元C轮融资,由Insight Partners领投,European Innovation Council (EIC),Accel,Salesforce Ventures,Hearst Ventures,Earlybird,Kibo跟投。

成立于2012年的CARTO,为客户提供一站式空间分析和位置智能服务,帮助数百万用户在进行动态地图数据展示和可视化。CARTO的主要目标客户来自商业公司,包括地产、零售、物流、金融服务、电信、政府部门等。

图片来源:CARTO

发力云处理技术

无论是地产公司,还是快消品企业,在工作中都会产生大量基于位置的数据。这些数据的存储、管理和分析,对于企业都是一个巨大的挑战。

为了帮助客户解决数据问题,CARTO首先帮助客户搭建好一个合适的空间数据库。基于客户的需求,CARTO提供云原生、私有化部署和混合部署的方式。同时,为了不给客户带来数据迁移的困扰和烦恼,CARTO近年来一直在扩充支持的数据源,目前可支持数据仓库(Amazon Redshift、Google BigQuery、Snowflake)、数据库(PostgreSQL、MySQL、Microsoft SQL Server)和云存储服务(Dropbox、Box、Google Drive)。用户可以直接连接到云端获取数据,也可以在本地上传历史数据。

搭建好数据库后,用户可以通过SQL语言查询和补充相关数据。除了客户自身的数据外,CARTO也从开源渠道和私人企业中收集了非常多的数据,包括道路交通数据、人口流动数据、金融数据、房地产数据、位置坐标数据(POI)等。CARTO总计有一万多个数据集,其中有3600个数据集是免费开放的数据。在SQL语言的基础上,CARTO还适配了spatial SQL语言。这种语言和SQL的基本逻辑和结构完全相同,但可以支持更多的空间分析方法。

补充好数据后,用户可以利用CARTO的云端系统Carto Builder进行空间分析,在短时间内创建地图。所有空间插件都支持在主要的数据仓库上运行,为用户提供高性能的、可扩展的、安全的地理空间分析套件。CARTO还开发了Cartoframes的Python软件包,可帮助客户将CARTO的功能整合到现有的项目中。

CARTO的理念是将所有的空间分析功能放上云端,让客户不再需要下载传统的GIS软件。既可以免去本地软件下载的麻烦,也可以带来联网即用的便利。

Carto目前的客户包括雷诺汽车、仲量联行、DHL、T-Mobile、可口可乐和万事达卡。

图片来源:CARTO

市场容量与中国竞争对手

根据市场预测,2020年全球位置智能市场估计为119亿美元,预计到2027年将达到298亿美元,复合年增长率达到14%。

经过9年的发展,CARTO目前已经建立了150多名员工的团队,分布在美国和欧洲。CARTO最早在西班牙马德里成立,曾用Vizzuality和CartoDB作为公司名。在2015年的2300万美元B轮融资时,将总部迁往了美国纽约,目前在马德里、塞维利亚和伦敦设有办事处。本轮以前,CARTO总计融资了约3100万美元。

36氪曾报道《全球地理数据行业迎来融资浪潮》,地理数据对于物流、零售、消费等行业有重大的意义,无论是选址、路径规划、人货场的综合分析,都离不开地理数据的应用。而我国恰好在物流、零售、消费等行业处于全球绝对领先的地位。随着全球的融资次数逐渐增加,国内的风投也会开始关注该领域的潜在机会。

36氪也访谈报道过国内的地理位置智能企业,包括极海、捷泰天域、亿景智联。极海的核心团队成员来自全球最大的地理信息技术公司Esri。捷泰天域的创始团队,也是出自Esri,与易智瑞(原Esri中国)有非常密切的合作关系。亿景智联在今年初完成数千万元A轮融资,创始人孙伟是百度前智能城市业务发展部总经理。

谷歌关闭其在伦敦的创业空间园区

Google正在关闭其在伦敦的自营创业空间,即Campus。这家硅谷科技巨头周一宣布,它已经决定 “不再重新开放 “位于东伦敦的Campus,此前它因冠状病毒大流行而被迫关闭。该公司说:”我们正在关闭Campus,以支持整个英国的初创企业,”该公司声称,它可以在没有实体空间的情况下为全国的初创企业提供支持。

2012年,当伦敦的初创企业开始起飞时,Campus London由以色列科技界资深人士和Google员工Eze Vidra开设。

Campus位于肖尔迪奇(Shoreditch)社区,离被称为 “硅环岛”的老街环岛系统只有几百米,这里常常被认为是伦敦科技城的中心,COVID-19肆虐之后,一些科技工作者说那里可能永远不会再是以前的样子。

Campus包括联合办公空间、咖啡馆和活动空间。它被各种加速器和创业项目使用,包括Seedcamp、Entrepreneur First、Code First和Silicon Drinkabout。多年来,这里举办了数千场活动,Google员工曾经来这里为初创企业提供免费指导。

Google现在表示,英国的创业社区 “不需要进入一个单一的共享物理空间,而是需要在任何地方获得大规模的资源、导师和项目”。

“当我在2012年第一次踏入伦敦Campus时,感觉就像有魔力一样,”Google英国创业公司负责人玛塔-克鲁宾斯卡在Twitter上说。”它在使伦敦成为一个成功的初创企业生态系统方面发挥了关键作用,经过近10年的时间,新的篇章已经开启。有很多事情值得庆祝,但仍有很多工作要做。”

2014年至2018年负责Campus的Sarah Drinkwater周一在一篇博客中说。”Campus在因COVID-19关闭后不会重新开放,这是对的。场景改变了,必须适应未来。”

在加入Campus之前曾在Google地图工作的Drinkwater说,如今伦敦有数百个协同工作空间,英国各地有几十家、几十家加速器。科技企业家、开发人员和投资者在社交媒体和博客文章中回忆了他们在Campus的时光:

“Wild Meta人工智能公司的首席执行官兼联合创始人阿曼丁-弗拉克斯(Amandine Flachs)写道,该公司旨在帮助视频游戏开发者通过机器学习创造更智能、更像人类的人工智能。邦希尔大街上的这个破旧的空间为许多不同的子社区提供了开始或聚集的容器,也为那些想了解’技术’是什么的令人难以置信的不同人物提供了进入的途径。我多次在咖啡馆遇到一个不确定的早期创始人,试图弄清楚它,然后在一年后遇到他们,他们有一个团队,有资金,有明确的前进方向。”

Google在马德里、圣保罗、首尔、特拉维夫、东京和华沙设有其他创业园区,目前Google并没有透露有关这些区域的未来计划。

谷歌地球在线虚拟现实功能:1秒穿越世界另一端

Google 今日上线了 Google Earth 的 VR 版本,让用户可以使用 HTC Vive 浏览 Google 地球中的部分城镇和景点。你可以在 Google Earth VR 版中像超人那样飞跃城市、回顾你曾经去过的旅程、甚至是抓住太阳来回拖拽以感受世界斗转星移的镜像。

Google Earth 是 Google 在 年发布的一款虚拟地球仪软件,它通过卫星拍照为全球大部分地区提供实景的俯瞰地图。并为少部分地区提供全 3D 建模的实景地图。

根据媒体的评测,Google Earth VR 版的体验在不同地区有着明显的差异,即便是在拥有 3D 建模的地区,也受到 Google 对这一地区数据采集质量的影响,大部分场景体验起来有一种老版本模拟人生的感觉。也因此,Google VR 默认推荐了一些值得观赏的地区,这些景点的视觉质量都很高,游览时仿佛身临其境。

另外,Google Earth VR 版暂时还没有搜索功能,因此你只能通过一次一次缩放来找到你想要去的地方。这毫无疑问的给用户带来了麻烦,但也有人表示这种感觉很震撼——你只有亲在在 Google Earth VR 里找过才知道东京和巴黎究竟是多么大的城市,而且当你找错了的时候也会体验到一座城市你所未见过的魅力。

这一次发布的 VR 版本,主要针对拥有 3D 建模的实景地图。目前,Google Earth VR 版仅适配了 HTC Vive,由于在其操控中涉及较为复杂的动作和运动追踪,暂时不能用于手机盒子和 Google 自家 VR 平台的 Daydream。Google 透露 Google Earth VR 从 2013 年就开始研发,是 Google 那个著名的「员工利用 20% 工作时间做一些自己感兴趣项目」计划的一部分,因此开发进度并不是很快。

这是微软发布的第二款 HTC Vive 应用,此前它还发布过一款可以让用户在虚拟空间里绘画的应用 Tilt Brush。Google 工程主管 Dominik Kaeser 解释说 Google 用了一种全新的技术保证用户即便在这款应用里像过山车那样飞来飞去,也不会觉得晕眩。

Google Earth VR 的产品经理 Mike Podwal 表示,他们的下一步计划是将 Earth VR 与更多的 Google 产品绑定以获得更多的数据和添加更多的图层。「我们希望你能在 VR 里体验到同一个地区不同时间、日期、季节、气候和人口数量时的变化。」

Google Earth VR 现已登陆游戏平台 Steam,感兴趣的朋友可以点击前往下载。