[](http://www.ixiaomei.com/)

小美搬家是我毕业后和同学一起开始的创业项目,就目前来说称作项目已经不太合适了,可以说它就是我的职业。小美搬家旨在为当代年轻的城市青年提供高质量的便捷搬家服务,简洁、快速、优质是我们不同传统搬家公司的主要特点,目前服务范围仅覆盖成都地区(今年刚起步( ̄▽ ̄))

我在小美搬家的承担主要任务是服务创新和技术开发,我们这一版的官网确认动工已经是去年这个时候的事儿了,服役一年几乎没有大的改动也差不多快审美疲劳了。之前设计的在线测价系统也是十分简陋的,随着客户转化流程的不断改进,这样的测价已经不能满足工作需要了。虽然新的网站已经开始筹备,但是这个问题迫在眉睫,于是决定提前将网站的在线测价系统更新。


整个测价系统中,涉及地理位置和路程测算的部分都是由 百度地图API 来实现的,本来一开始考虑使用 Web API,最后发现 Javascript SDK 才是更适合我们的真爱。但是即使是功能繁多的 SDK ,有一些需求依然不能解决,比如:区分驾车行程在三环内外各有多少。

问题描述

由于我们的搬家服务对于三环内外车程的计费方式是不同的,所以如果测价里面不能区分三环内外那么测出来的价格也就失去了参考价值(总不能让用户测好填进来吧,操作成本太高)。

否定的方案

  1. 把地址做成预设的点,点对点选择,点点间路程数据预先测算好。
    这个方案就不多说了,假定100个点(好少),C100(2)= 4950, wakaka~ 已经哭晕在厕所

  2. 让客户来选择搬出到点是否在三环内测,跨三环的平分车程
    不用怎么推敲就知道不靠谱

  3. 在2的基础上,如果跨三环,让客户选定最近的三环立交
    如果遇到两点都在三环外,但主要车程都在三环上的情况怎么办?

灵感来源

在调试 百度地图SDK 的时候,发现有在一个圆范围内搜索目标的 demo,而成都的三环也近似圆形,似乎可用。但是在看过源码之后,无比失望.。o○ ○o。. 百度 demo 里面的范围内搜索虽然表示的是一个圆,但其实那只是一个用来标识的覆盖物,真正的搜索是在一个正方形的坐标范围内进行的。虽然百度的 demo 没什么用,但就在这里,我看到了解决问题的关键——坐标——有了坐标就变成数学问题了。

解决思路

百度地图搜索的结果里面是带有经纬坐标的,这个坐标叫百度坐标(为了军事保密,不是准确经纬坐标)。这个坐标是一个球面坐标,计算需换算成平面坐标来进行,后面详解。

有坐标之后,以市中心为原点画圆,使圆尽量与三环重合,得圆的方程。

搜索结果中有搬到地两个点的坐标,连线,得直线方程。

将直线与圆求切点,会有两种情况:

  1. 没有切点或一个切点
    这说明两地都在三环外,且不用走三环,测算的车程全为三环外车程

  2. 两个切点

    1. 两点都在圆内
      前面白算了,全是三环内车程

    2. 一个点在圆内,一个点在圆外
      求两点连线段在圆内部分的比例,正比与车程,得三环内外车程的估值

    3. 两点在圆外同侧
      不用走三环,测算的车程全为三环外车程

    4. 两点在圆外异侧
      求圆内切线段占两点连线段的比例,正比车程,得三环外和三环上的车程估值

计算公式什么的,就没必要列出来了吧

关于坐标

通常情况下,我们使用的经纬度坐标,地球是球形的,所以经纬度坐标表示的是一个球面,称为球面坐标。
而在我们的实际计算当中,是在平面坐标系中解决问题的,使用的应该是平面坐标。
所以前面提到需要讲球面坐标转换为平面坐标,这个功能在百度地图的 SDK 里是有的

# 根据球面坐标获得平面坐标
get_mecator = (poi) ->
    map.getMapType().getProjection().lngLatToPoint(poi)

至于不转换坐标直接计算会怎么样?我推测会导致圆方程的形状畸变,实际覆盖范围变大,具体会有什么影响没研究过。

一些数据

一些计算中使用的数据,成都有相同需求的盆友可以借鉴

原点设置为 天府广场地铁站
球面坐标 104.072486, 30.66348
平面坐标(百度) 11585422.2, 3567130.97
计算方式 dot = get_mecator(new BMap.Point(104.072486, 30.66348))
半径设置为 9300

源码(coffeescript)

https://gist.github.com/yiichou/ab3970341008b04a788c

其他

这个方法其实不只适用于成都一个城市,比如北京,它的环是方形的,构建方形的函数方程即可;武汉,三镇分成三个独立的函数,求解应该也是可以的;重庆,呃..( °Д°)..这样的城市,内外远近什么的不是第一考虑要素了吧,妈蛋

然后呢,如分析所见,这也是个近似求解,结果的话还算靠谱

在这之后发现这套系统仍有问题,天杀的百度地图有些点返回的坐标是错的,妈蛋(直接在百度地图的网页上搜又没问题,居然使用的不同的数据库,百度好贱 (¯﹃¯))