<?php
/**
*
* @author Administrator
*
*/
class MapTools {
public static function model() {
return new MapTools ();
}
/**
* 判断点是否在矩形内
*
* @param
* {Point} point 点对象
* @param
* {Bounds} bounds 矩形边界对象
* @return s {Boolean} 点在矩形内返回true,否则返回false
*/
function isPointInRect($point, $bounds) {
// 西南脚点
$sw = $bounds ['sw'];
// 东北脚点
$ne = $bounds ['ne'];
return ($point ['lng'] >= $sw ['lng'] && $point ['lat'] >= $sw ['lat'] && $point ['lng'] <= $ne ['lng'] && $point ['lat'] <= $ne ['lat']);
}
/**
* 返回一个多边形的最小外矩形(西南点和东北点的坐标)
*
* @param array $polygon
*/
function getBoundsByPolygon($polygon) {
$least_lng = $polygon [0] ['lng'];
$least_lat = $polygon [0] ['lat'];
$largest_lng = $polygon [0] ['lng'];
$largest_lat = $polygon [0] ['lat'];
foreach ( $polygon as $point ) {
if ($point ['lng'] < $least_lng) {
$least_lng = $point ['lng'];
}
if ($point ['lat'] < $least_lat) {
$least_lat = $point ['lat'];
}
if ($point ['lng'] > $largest_lng) {
$largest_lng = $point ['lng'];
}
if ($point ['lat'] > $largest_lat) {
$largest_lat = $point ['lat'];
}
}
return array (
'sw' => array (
'lng' => $least_lng,
'lat' => $least_lat
),
'ne' => array (
'lng' => $largest_lng,
'lat' => $largest_lat
)
);
}
/**
* 判断点是否在多边形内
*
* @param unknown_type $point
* @param unknown_type $polygon
* @return boolean
*/
function isPointInPolygon($point, $polygon) {
if (empty ( $polygon )) {
return false;
}
// 首先判断点是否在多边形的外包矩形内,如果在,则进一步判断,否则返回false
// 可以通过绘制矩形时,补充多边形的中心进行计算处理.
$polygonBounds = $this->getBoundsByPolygon ( $polygon );
if (! $this->isPointInRect ( $point, $polygonBounds )) {
return false;
}
$pts = $polygon;
// 获取多边形点
// 下述代码来源:http://paulbourke.net/geometry/insidepoly/,进行了部分修改
// 基本思想是利用射线法,计算射线与多边形各边的交点,如果是偶数,则点在多边形外,否则
// 在多边形内。还会考虑一些特殊情况,如点在多边形顶点上,点在多边形边上等特殊情况。
$N = count ( $pts );
$boundOrVertex = true;
// 如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
$intersectCount = 0;
// cross points count of x
$precision = 2e-10;
// 浮点类型计算时候与0比较时候的容差
$p1 = $p2 = null;
// neighbour bound vertices
$p = $point;
// 测试点
$p1 = $pts [0];
// left vertex
for($i = 1; $i <= $N; ++ $i) {
// check all rays
if ($p ['lng'] == $p1 ['lng'] && $p ['lat'] == $p1 ['lat']) {
return $boundOrVertex;
// p is an vertex
}
$p2 = $pts [$i % $N];
// right vertex
if ($p ['lat'] < min ( $p1 ['lat'], $p2 ['lat'] ) || $p ['lat'] > max ( $p1 ['lat'], $p2 ['lat'] )) {
// ray
// is
// outside
// of
// our
// interests
$p1 = $p2;
continue;
// next ray left point
}
if ($p ['lat'] > min ( $p1 ['lat'], $p2 ['lat'] ) && $p ['lat'] < max ( $p1 ['lat'], $p2 ['lat'] )) {
// ray
// is
// crossing
// over
// by
// the
// algorithm
// (common
// part
// of)
if ($p ['lng'] <= max ( $p1 ['lng'], $p2 ['lng'] )) {
// x is before of
// ray
if ($p1 ['lat'] == $p2 ['lat'] && $p ['lng'] >= min ( $p1 ['lng'], $p2 ['lng'] )) {
// overlies
// on
// a
// horizontal
// ray
return $boundOrVertex;
}
if ($p1 ['lng'] == $p2 ['lng']) {
// ray is vertical
if ($p1 ['lng'] == $p ['lng']) {
// overlies on a vertical ray
return $boundOrVertex;
} else {
// before ray
++ $intersectCount;
}
} else {
// cross point on the left side
$xinters = ($p ['lat'] - $p1 ['lat']) * ($p2 ['lng'] - $p1 ['lng']) / ($p2 ['lat'] - $p1 ['lat']) + $p1 ['lng'];
// cross
// point
// of
// lng
if (abs ( $p ['lng'] - $xinters ) < $precision) {
// overlies on
// a ray
return $boundOrVertex;
}
if ($p ['lng'] < $xinters) {
// before ray
++ $intersectCount;
}
}
}
} else { // special case when ray is crossing through the vertex
if ($p ['lat'] == $p2 ['lat'] && $p ['lng'] <= $p2 ['lng']) {
// p crossing
// over
// p2
$p3 = $pts [($i + 1) % $N];
// next vertex
if ($p ['lat'] >= min ( $p1 ['lat'], $p3 ['lat'] ) && $p ['lat'] <= max ( $p1 ['lat'], $p3 ['lat'] )) {
// p.lat
// lies
// between
// p1.lat
// &
// p3.lat
++ $intersectCount;
} else {
$intersectCount += 2;
}
}
}
$p1 = $p2;
// next ray left point
}
if ($intersectCount % 2 == 0) {
// 偶数在多边形外
return false;
} else {
// 奇数在多边形内
return true;
}
}
/**
* 签名校验
*
* @param unknown $ak
* @param unknown $sk
* @param unknown $url
* @param unknown $querystring_arrays
* @param string $method
* @return string
*/
function caculateAKSN($ak, $sk, $url, $querystring_arrays, $method = 'GET') {
if ($method === 'POST') {
ksort ( $querystring_arrays );
}
$querystring = http_build_query ( $querystring_arrays );
return md5 ( urlencode ( $url . '?' . $querystring . $sk ) );
}
/**
* 通过地址返回坐标
*
* @param string $address_name
* @return mixed|boolean
*/
function getLocationByAddress($address_name) {
// API控制台申请得到的ak(此处ak值仅供验证参考使用)
$ak = 'xxxxxxxxxxxxxx';
// 应用类型为for server, 请求校验方式为sn校验方式时,系统会自动生成sk,可以在应用配置-设置中选择Security
// Key显示进行查看(此处sk值仅供验证参考使用)
$sk = 'xxxxxxxxxxxxxxxxx';
// 以Geocoding服务为例,地理编码的请求url,参数待填
$url = "http://api.map.baidu.com/geocoder/v2/?address=%s&output=%s&ak=%s&sn=%s";
// get请求uri前缀
$uri = '/place/v2/search';
// 地理编码的请求output参数
$output = 'json';
$pois = '0';
$query = $address_name;
$region = '全国';
$scope = 1;
$querystring_arrays = array (
'query' => $query,
'output' => $output,
'ak' => $ak,
'scope' => $scope,
'region' => $region
);
$url = "http://api.map.baidu.com/place/v2/search?query=%s&output=%s&ak=%s&sn=%s&scope=%s®ion=%s";
// 调用sn计算函数,默认get请求
$sn = $this->caculateAKSN ( $ak, $sk, $uri, $querystring_arrays );
// 请求参数中有中文、特殊字符等需要进行urlencode,确保请求串与sn对应
$target = sprintf ( $url, urlencode ( $query ), $output, $ak, $sn, $scope, urlencode ( $region ) );
// 输出计算得到的sn
// echo "sn: $sn \n";
// 输出完整请求的url(仅供参考验证,故不能正常访问服务)
// echo "url: $target \n";
$content = file_get_contents ( $target );
$content = json_decode ( $content, true );
if ($content ['status'] == 0 && isset ( $content ['results'] ) && ! empty ( $content ['results'] ) && isset ( $content ['results'] [0] ['location'] ) && ! empty ( $content ['results'] [0] ['location'] )) {
// var_export ( $content );
return $content ['results'] [0] ['location'];
}
return false;
}
public function getAddressByLocation($longitude, $latitude) {
$url = "http://api.map.baidu.com/geocoder/v2/?ak=thT0201pFtgt3VApRT2mhlA6mmpQUnWQ&location={$latitude},{$longitude}&output=json";
$ch = curl_init ( $url );
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true );
// 获取数据返回
curl_setopt ( $ch, CURLOPT_BINARYTRANSFER, true );
// 在启用
// CURLOPT_RETURNTRANSFER
// 时候将获取数据返回
$output = curl_exec ( $ch );
$arr = json_decode ( $output, true );
if (! $arr || $arr ['status'] || ! isset ( $arr ['result'] ))
return false;
return $arr ['result'] ['formatted_address'];
}
}
