谷歌画电子围栏,根据已知起点计算去是否在围栏内


# 电子围栏

<!DOCTYPE html>
<html>
<style>
#map {
  width: 760px;
  height: 400px;
  top: 10px;
  bottom: 0;
}
.search-button {
    display: inline-block;
    padding: 3px 20px;
    background-color: #4CAF50; /* 按钮背景颜色 */
    color: white; /* 文字颜色 */
    cursor: pointer;
    border-radius: 5px; /* 圆角 */
    text-align: center;
    font-size: 16px;
}
.search-button:hover {
    background-color: #45a049; /* 鼠标悬停时的背景颜色 */
}
</style>
<body >
  <form id="edit-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="">
    <div class="form-group">
      <label class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
      <div class="col-xs-12 col-sm-8">
          <input id="c-name" class="form-control" name="row[name]" type="text" value="">
      </div>
    </div>
    <div class="form-group">
        <label class="control-label col-xs-12 col-sm-2">{:__('Lnglat')}:</label>
        <div class="col-xs-12 col-sm-8">
            <input id="c-lnglat" readonly class="form-control" name="row[lnglat]" type="text" value="">
        </div>
    </div>
    <div class="form-group">
      <label class="control-label col-xs-12 col-sm-2">{:__('搜索地址')}:</label>
      <div class="col-xs-12 col-sm-8">
          <input id="addressInput" class="form-control" type="text" placeholder="输入地址">
      </div>
      <span class="search-button" onclick="geocodeAddress()">搜索</span>
  </div>
    <div id="map"></div>
    <div class="form-group layer-footer">
        <label class="control-label col-xs-12 col-sm-2"></label>
        <div class="col-xs-12 col-sm-8">
            <button type="submit" class="btn btn-primary btn-embossed disabled">{:__('保存')}</button>
        </div>
    </div>
</form>
</body>
</html>
<!--YOUR_API_KEY-->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAQX1s8K_pLW1pcEsd2H9NAADoHWi2_kbQ&libraries=drawing"></script>

<script>
function geocodeAddress() {
    var geocoder = new google.maps.Geocoder();
    var address = document.getElementById('addressInput').value;
    geocoder.geocode({ 'address': address }, function(results, status) {
        if (status === 'OK') {
            map.setCenter(results[0].geometry.location);
            map.setZoom(15);  // 设置缩放级别,以便更清晰地显示位置
            // 清除之前的绘图(如果有)
            drawingManager.setDrawingMode(null);
            drawingManager.setMap(null);
            drawingManager.setMap(map);  // 重新设置绘图工具
        } else {
            alert('无法找到该地址:' + status);
        }
    });
}
const map = new google.maps.Map(document.getElementById("map"), {
    center: { lat: -34.397, lng: 150.644 },
    zoom: 8,
  });
  const drawingManager = new google.maps.drawing.DrawingManager({
    drawingMode: google.maps.drawing.OverlayType.MARKER,
    drawingControl: true,
    drawingControlOptions: {
      position: google.maps.ControlPosition.TOP_CENTER,
      drawingModes: [
        google.maps.drawing.OverlayType.POLYGON, //绘制多边形围栏
        // google.maps.drawing.OverlayType.MARKER,
        // google.maps.drawing.OverlayType.CIRCLE,
        // google.maps.drawing.OverlayType.POLYLINE,
        // google.maps.drawing.OverlayType.RECTANGLE,
      ],
    },
    markerOptions: {
      icon: "https://developers.google.com/maps/documentation/javascript/examples/full/images/beachflag.png",
    },
    circleOptions: {
      fillColor: "#ffff00",
      fillOpacity: 1,
      strokeWeight: 5,
      clickable: false,
      editable: true,
      zIndex: 1,
    },
  });
  drawingManager.setMap(map);
  // 获取电子围栏值
  google.maps.event.addListener(drawingManager, 'polygoncomplete', function(poly) {
      polygon = poly;
      getPolygonCoordinates();
  });
  function getPolygonCoordinates() {
    var path = polygon.getPath();
    var coordinates = [];
    for (var i = 0; i < path.getLength(); i++) {
        coordinates.push({
            lat: path.getAt(i).lat(),
            lng: path.getAt(i).lng()
        });
  }
  let arrobj = coordinates.map(item =>{
    console.log(JSON.stringify(item));
    return JSON.stringify(item)
  })
  $("#c-lnglat").val(arrobj)
  console.log("多边形顶点坐标:", arrobj);
 }
</script>

# 保存电子围栏数据

public function add(){
    if (false === $this->request->isPost()) {
        return $this->view->fetch();
    }
    $params = $this->request->post('row/a');
    if (empty($params)) {
        $this->error(__('Parameter %s can not be empty', ''));
    }
    if(!$params['name']){
        $this->error('请输入电子围栏名称');
    }
    if(!$params['lnglat']){
        $this->error('请先画电子围栏');
    }
    // 去除开头和结尾的花括号
    $str = trim($params['lnglat'], '{}');
    // 分割字符串为单个项目
    $items = explode('},{', $str);
    // 初始化一个空数组来存储结果
    $result = [];
    // 遍历每个项目并将其转换为关联数组
    foreach ($items as $item) {
        // 添加花括号以便json_decode可以解析
        $item = '{' . $item . '}';
        // 将字符串解析为关联数组
        $arr = json_decode($item, true);
        // 将解析后的数组添加到结果数组中
        $result[] = $arr;
    }
    // 输出结果
    $params['lnglat'] =json_encode($result);
    var_dump($params);
    $this->success();
}

# 根据已知起点计算去是否在围栏内APi接口

$demo = getMapKm("34.723538,113.729059", "34.747021,113.658247", 1);
if($demo == 0){
    $this->error('起点不在电子围栏内');
}
var_dump($demo);
exit;



/**
 * Undocumented function
 * 获取谷歌地图两个点之间的行车距离
 * @Author Ixiangang
 * @DateTime 2024-07-25
 * @param [type] $origin 起点
 * @param [type] $destination 终点
 * @param integer $enclosure 1 = 是否需要检测是否在电子围栏内
 * @return void
 */

function getMapKm($origin, $destination, $enclosure = 0)
{
    // 检测是不是在电子围栏内
    if ($enclosure == 1) {
        $origin_arr = explode(',', $origin);
        $mapence = \think\Db::name('mapence')->column('lnglat', 'id');
        foreach ($mapence as $v) {
            $vertices = json_decode($v, true);
            $enc[]  = isPointInsidePolygon($origin_arr[0], $origin_arr[1], $vertices);
        }
        # 不在电子围内返回 0
        if (!in_array(1, $enc)) {
            return 0;
        }
    }
    // 设置API key
    $apiKey = 'AIzaSyB1VvStv3DmL5yu3hqZccjifY8P6b4MrIc'; //替换为你的Google Maps API密钥
    // 构建请求URL
    $url = 'https://maps.googleapis.com/maps/api/directions/json?origin=' . $origin . '&destination=' . $destination . '&key=' . $apiKey;
    // 使用file_get_contents发送请求,或者使用cURL库
    $json_response = file_get_contents($url);
    // 解码JSON响应
    $response = json_decode($json_response, true);
    // 检查响应是否成功
    if ($response['status'] == 'OK') {
        // 提取路线数组
        $routes = $response['routes'];
        // 假设我们只关心第一条路线
        $route = $routes[0];
        // 提取路线上的步骤数组
        $legs = $route['legs'];
        // 假设我们只关心第一条路线的第一个步骤
        $leg = $legs[0];
        // 提取步骤的距离
        $distance = $leg['distance'];

        $distance = $leg['distance'];
        // 输出距离
        //echo "行车路线的距离是:" . $distance['text'] . "\n";
        $value  = $distance['value'] / 1000;  //千米
        return number_format($value, 1);
    } else {
        //echo "无法计算距离,请检查API请求是否成功。";
        return 0;
    }
}


/**
 * 查看是否在电子围栏内
 * @Author Ixiangang
 * @DateTime 2024-07-25
 * @param [type] $point_lat 起点维度
 * @param [type] $point_lng 起点经度
 * @param [type] $vertices 画电子围栏经纬
 * @return boolean
 */
function isPointInsidePolygon($point_lat, $point_lng, $vertices)
{
    $x = $point_lat;
    $y = $point_lng;
    $inside = false;
    $count = count($vertices);
    for ($i = 0, $j = $count - 1; $i < $count; $j = $i++) {
        $xi = $vertices[$i]['lat'];
        $yi = $vertices[$i]['lng'];
        $xj = $vertices[$j]['lat'];
        $yj = $vertices[$j]['lng'];
        $intersect = (($yi > $y) != ($yj > $y)) &&
            ($x < ($xj - $xi) * ($y - $yi) / ($yj - $yi) + $xi);
        if ($intersect) $inside = !$inside;
    }
    return $inside;
}

# 谷歌文档地图
https://developers.google.com/maps/documentation/javascript/drawinglayer?hl=zh-cn#maps_drawing_tools-javascript

posted @ 2024-07-25 13:44  丶XianGang  阅读(23)  评论(0编辑  收藏  举报