100个点位的坐标系数组,如何按照距离近的均分10组,每组10个坐标点呢?

按照距离近的均分10组,如何用PHP出来啊,能否给个思路:sweat_smile:

[{"lat":35.874896945057856,"lng":120.0464390775317},
{"lat":35.88588325548392,"lng":119.99590712196652},
{"lat":35.951515,"lng":120.21981},
{"lat":35.884468,"lng":120.02675},
{"lat":36.0084114074707,"lng":119.71817016601562},
{"lat":35.897594,"lng":120.03817},
{"lat":35.970177,"lng":120.23091},
{"lat":36.06714,"lng":120.119095},
{"lat":35.90232,"lng":120.034294},
{"lat":35.965301513671875,"lng":120.22760772705078},
{"lat":35.89666,"lng":120.037224},
{"lat":35.97272012635486,"lng":120.14654847991817},
{"lat":35.964363,"lng":120.223564},
{"lat":35.83966827392578,"lng":119.98360443115234},
{"lat":35.99657440185547,"lng":119.89422607421876},
{"lat":35.94984436035156,"lng":120.15196228027344},
{"lat":35.9611,"lng":120.18144},
{"lat":35.66075,"lng":119.57073},
{"lat":35.934139251708984,"lng":120.13544464111328},
{"lat":36.10059,"lng":120.10494},
{"lat":35.946648,"lng":120.16422},
{"lat":35.688347,"lng":119.857346},
{"lat":35.95534487636738,"lng":120.18470071470776},
{"lat":36.02797,"lng":119.98739},
{"lat":35.9548225402832,"lng":120.17434692382812},
{"lat":36.03295,"lng":120.16756},
{"lat":35.98513,"lng":120.146736},
{"lat":35.842606,"lng":119.98231},
{"lat":36.007046,"lng":120.16161},
{"lat":35.96545,"lng":120.23893},
{"lat":35.90878,"lng":120.024666},
{"lat":35.861046,"lng":119.91485},
{"lat":35.907917,"lng":119.917946},
{"lat":35.8882598876953,"lng":119.9836883544922},
{"lat":35.889233,"lng":120.002914},
{"lat":35.891658782959006,"lng":120.02381896972655},
{"lat":35.865788,"lng":120.02499},
{"lat":36.03559,"lng":120.21756},
{"lat":35.87194634845571,"lng":119.99274297995171},
{"lat":35.95242,"lng":120.18444},
{"lat":35.70124816894531,"lng":119.76522064208984},
{"lat":35.832195,"lng":119.98379},
{"lat":36.021984,"lng":120.14496},
{"lat":35.772263,"lng":119.62605},
{"lat":35.90007,"lng":120.0358},
{"lat":35.88225970988175,"lng":119.99193653349472},
{"lat":35.966346740722656,"lng":120.16938018798828},
{"lat":35.88001,"lng":119.98775},
{"lat":35.90878,"lng":120.024666},
{"lat":35.89633,"lng":120.067795},
{"lat":35.87116,"lng":119.97676},
{"lat":36.040035,"lng":120.220245},
{"lat":35.940014,"lng":120.22272},
{"lat":35.96353530883789,"lng":120.1564712524414},
{"lat":35.98515,"lng":120.15133},
{"lat":35.899288177490234,"lng":120.02743530273438},
{"lat":35.82219266374146,"lng":119.9758404575779},
{"lat":35.960884,"lng":120.186485},
{"lat":35.87227249145507,"lng":120.02003479003905},
{"lat":35.962345,"lng":120.19188},
{"lat":35.975105,"lng":120.1849},
{"lat":35.974297,"lng":120.16681},
{"lat":35.878997802734375,"lng":120.00605010986328},
{"lat":36.008472442626974,"lng":119.71774291992188},
{"lat":35.974346,"lng":120.144905},
{"lat":35.971240570361736,"lng":120.18688173996705},
{"lat":35.93595,"lng":120.15261},
{"lat":35.882557,"lng":119.989265},
{"lat":35.871624,"lng":119.99343},
{"lat":35.97241180577667,"lng":120.2400133842267},
{"lat":35.89035,"lng":120.01768},
{"lat":35.95125628388685,"lng":120.1546811498479},
{"lat":35.92319194070047,"lng":120.02688905501668},
{"lat":35.862522,"lng":119.98052},
{"lat":36.04382,"lng":120.22242},
{"lat":36.018784,"lng":120.13498},
{"lat":36.046375,"lng":120.22158},
{"lat":35.884106,"lng":120.01076},
{"lat":35.86269,"lng":120.03086},
{"lat":35.88063812255859,"lng":120.05042266845702},
{"lat":35.987392,"lng":120.17108},
{"lat":35.9599,"lng":120.17881},
{"lat":35.97542163108799,"lng":120.16095582560064},
{"lat":36.01217,"lng":120.170555},
{"lat":36.016594,"lng":120.10898},
{"lat":35.87997,"lng":119.96322},
{"lat":35.852184,"lng":119.98207},
{"lat":35.95140457153322,"lng":120.163330078125},
{"lat":36.051678,"lng":120.09322},
{"lat":35.965744,"lng":120.18317},
{"lat":35.881298,"lng":119.99375},
{"lat":35.92774963378906,"lng":120.16067504882812},
{"lat":35.996346,"lng":120.12563},
{"lat":35.886524,"lng":120.06672},
{"lat":35.96708,"lng":120.219284},
{"lat":36.016865,"lng":120.138176},
{"lat":35.98428,"lng":120.17224},
{"lat":35.898636,"lng":120.0706},
{"lat":35.884468,"lng":120.02675},
{"lat":35.8964,"lng":120.03528}]
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 8

先按距离排序,再array_chunk

1年前 评论

因评论太长,你给的坐标点我只贴了20个,你自己拿着代码测

<?php

$points = '[{"lat":35.874896945057856,"lng":120.0464390775317},{"lat":35.88588325548392,"lng":119.99590712196652},{"lat":35.951515,"lng":120.21981},{"lat":35.884468,"lng":120.02675},{"lat":36.0084114074707,"lng":119.71817016601562},{"lat":35.897594,"lng":120.03817},{"lat":35.970177,"lng":120.23091},{"lat":36.06714,"lng":120.119095},{"lat":35.90232,"lng":120.034294},{"lat":35.965301513671875,"lng":120.22760772705078},{"lat":35.89666,"lng":120.037224},{"lat":35.97272012635486,"lng":120.14654847991817},{"lat":35.964363,"lng":120.223564},{"lat":35.83966827392578,"lng":119.98360443115234},{"lat":35.99657440185547,"lng":119.89422607421876},{"lat":35.94984436035156,"lng":120.15196228027344},{"lat":35.9611,"lng":120.18144},{"lat":35.66075,"lng":119.57073},{"lat":35.934139251708984,"lng":120.13544464111328},{"lat":36.10059,"lng":120.10494}]';
$points = json_decode($points, true);

// step1 求得N个坐标点的中心点
$center = getPointsCenter($points);
echo 'N个坐标点的中心点: ' . json_encode($center) . PHP_EOL;

// step2 计算每个点与中心点的距离
foreach ($points as $key => $point) {
    $points[$key]['distance'] = getDistance($point['lng'], $point['lat'], $center[1], $center[0], 1);
}

// step3 根据距离升序排序
array_multisort(array_column($points, 'distance'), SORT_ASC, $points);

// step4 切割数组
$result = array_chunk($points, 10);
var_dump($result);

/**
 * 返回中心点的数组[纬度lat,经度lng]
 * @param array $points eg. [{"lat":35.88,"lng":119.99}]
 * @return float[]|int[]
 */
function getPointsCenter($points)
{
    $PI = pi();
    $x = $y = $z = 0;
    foreach ($points as $point) {
        if (empty($point['lat']) || empty($point['lng'])) {
            continue;
        }
        $lat = $point['lat'] * $PI / 180.0;
        $lng = $point['lng'] * $PI / 180.0;

        $x += cos($lat) * cos($lng);
        $y += cos($lat) * sin($lng);
        $z += sin($lat);
    }
    $count = count($points);
    $x = $x / $count;
    $y = $y / $count;
    $z = $z / $count;

    $tmp_lng = atan2($y, $x);
    $tmp_lat = atan2($z, sqrt($x * $x + $y * $y));

    return [$tmp_lat * 180 / $PI, $tmp_lng * 180 / $PI];
}

/**
 * 计算两点地理坐标之间的距离
 * @param string $longitude1 起点经度
 * @param string $latitude1 起点纬度
 * @param string $longitude2 终点经度
 * @param string $latitude2 终点纬度
 * @param Int $unit 单位 1:米 2:公里
 * @param Int $decimal 精度 保留小数位数
 * @return float
 */
function getDistance($longitude1, $latitude1, $longitude2, $latitude2, $unit = 2, $decimal = 2)
{
    $EARTH_RADIUS = 6370.996; // 地球半径系数
    $PI = pi();

    $radLat1 = $latitude1 * $PI / 180.0;
    $radLat2 = $latitude2 * $PI / 180.0;

    $radLng1 = $longitude1 * $PI / 180.0;
    $radLng2 = $longitude2 * $PI / 180.0;

    $a = $radLat1 - $radLat2;
    $b = $radLng1 - $radLng2;

    $distance = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2)));
    $distance = $distance * $EARTH_RADIUS * 1000;

    if ($unit == 2) {
        $distance = $distance / 1000;
    }

    return round($distance, $decimal);
}
1年前 评论
jinduo (楼主) 1年前
忆往昔弹指间 (作者) 1年前

file
这样的分布方式,怎么算啊

1年前 评论

已实现

public function redisGeo(Request $request){
        $client = new Client(config('database.redis.default'));
        $stores = Store::whereIn('id',$request['stores'])->where('is_hidden','F')->get(['id','location','title']);
        $users=$request['users'];
        $response=$this->getStore($stores,$users,$client);
        return $response;

    }
    public function getStore($stores,$users,$client){
        $num=intval(count($stores)/count($users));
        $response=[];
        foreach ($users as $user){
            $data=[];
            foreach ($stores as $store){
                $location = json_decode($store['location'],true);
                $client->geoadd("store" ,$location['lng'],$location['lat'],$store['id']);
                $distance = $client->geodist('store',$stores[0]['id'],$store['id'],'km');
                $data[] = [
                    'id' => $store['id'],
                    'distance' => number_format($distance,2),
                    'location'=>$store['location'],
                    'title'=>$store['title']
                ];
            }
            $sort=array_column($data, 'distance');
            array_multisort($sort, SORT_ASC, $data);
            $any=array_splice($data,$num);
            $response[]=[
                'user_id'=>$user,
                'stores'=>$data,
                'length'=>count($data)
            ];
            $stores=$any;
        }
        return $response;
    }
1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!