文件
mashangyoujiu/Application/SmallProgramApi/Helper/FenceHelper.class.php

133 行
4.8 KiB
PHP

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

<?php
namespace SmallProgramApi\Helper;
/**
* 电子围栏辅助类
* 用于判断坐标点是否在电子围栏内
*/
class FenceHelper
{
/**
* 判断点是否在多边形内(射线法)
* @param float $lng 经度
* @param float $lat 纬度
* @param array $polygon 多边形坐标数组 [['lng' => x, 'lat' => y], ...]
* @return bool
*/
public static function isPointInPolygon($lng, $lat, $polygon)
{
if (empty($polygon) || count($polygon) < 3) {
return false;
}
$count = count($polygon);
$inside = false;
for ($i = 0, $j = $count - 1; $i < $count; $j = $i++) {
$xi = $polygon[$i]['lng'];
$yi = $polygon[$i]['lat'];
$xj = $polygon[$j]['lng'];
$yj = $polygon[$j]['lat'];
if ((($yi > $lat) != ($yj > $lat)) &&
($lng < ($xj - $xi) * ($lat - $yi) / ($yj - $yi) + $xi)) {
$inside = !$inside;
}
}
return $inside;
}
/**
* 判断点是否在任意一个围栏内
* @param float $lng 经度
* @param float $lat 纬度
* @param array $fences 围栏数据数组
* @return array 返回结果 ['in_fence' => bool, 'fence_name' => string]
*/
public static function checkPointInFences($lng, $lat, $fences)
{
if (empty($fences)) {
return ['in_fence' => false, 'fence_name' => ''];
}
foreach ($fences as $fence) {
// 只检查启用的围栏
if (isset($fence['is_active']) && $fence['is_active'] != 1) {
continue;
}
// 只处理多边形围栏
if (isset($fence['fence_type']) && $fence['fence_type'] != 1) {
continue;
}
$fenceData = $fence['fence_data'];
// 如果fence_data是字符串,尝试解析
if (is_string($fenceData)) {
$fenceData = json_decode($fenceData, true);
if (json_last_error() !== JSON_ERROR_NONE) {
continue;
}
}
// 如果fence_data是数组格式(新格式)
if (is_array($fenceData)) {
// 检查是否是多个多边形的数组格式
if (isset($fenceData[0]) && is_array($fenceData[0])) {
// 新格式:[{id: '', paths: [{lat: x, lng: y}]}, ...]
if (isset($fenceData[0]['paths'])) {
foreach ($fenceData as $polygon) {
if (isset($polygon['paths']) && is_array($polygon['paths'])) {
$points = [];
foreach ($polygon['paths'] as $point) {
if (isset($point['lat']) && isset($point['lng'])) {
$points[] = ['lng' => $point['lng'], 'lat' => $point['lat']];
}
}
if (count($points) >= 3 && self::isPointInPolygon($lng, $lat, $points)) {
return [
'in_fence' => true,
'fence_name' => $fence['fence_name'] ? $fence['fence_name'] : '配送区域'
];
}
}
}
}
// 旧格式:直接是坐标点数组 [{lng: x, lat: y}, ...]
else {
$points = [];
foreach ($fenceData as $point) {
if (isset($point['lng']) && isset($point['lat'])) {
$points[] = ['lng' => $point['lng'], 'lat' => $point['lat']];
}
}
if (count($points) >= 3 && self::isPointInPolygon($lng, $lat, $points)) {
return [
'in_fence' => true,
'fence_name' => $fence['fence_name'] ? $fence['fence_name'] : '配送区域'
];
}
}
}
}
}
return ['in_fence' => false, 'fence_name' => ''];
}
/**
* 获取门店的电子围栏数据
* @param int $storeId 门店ID
* @return array
*/
public static function getStoreFences($storeId)
{
$FenceModel = new \Common\Model\StoreDeliveryFenceModel();
return $FenceModel->where(['store_id' => $storeId, 'is_active' => 1])->select();
}
}