Sphinx Search: есть ли способ найти результаты в пределах нескольких миль от маршрута, например, по ломаной линии, а не по полигону - PullRequest
1 голос
/ 08 мая 2020

Я хочу искать записи в Sphinx Search, которые находятся в пределах «X» миль от «ломаной линии», записи могут находиться по обе стороны от ломаной линии. У меня есть набор геокодирования, который формирует маршрут.

$polylineLatLon = array("48.1390965,11.580255","48.2617271,11.6472244","48.3885849,11.5972817","48.5191226,11.5829265","48.6465704,11.516","48.773632,11.4611113","48.9037728,11.4703166","49.0096128,11.3544774","49.1298187,11.272155","49.2569017,11.2146807","49.3872571,11.2021279","49.5046949,11.2919927","49.6166182,11.3960946","49.7263312,11.5053892","49.8565686,11.51806","49.9767852,11.606766","50.0952959,11.6940558","50.2140534,11.7813241","50.3446984,11.7877614","50.4762554,11.8022454","50.6064391,11.791023","50.7318807,11.8482506","50.8638132,11.8523812","50.9891474,11.9091797","51.1166811,11.9561183","51.2372088,12.0594156","51.3430381,12.1846855","51.4732111,12.2154129","51.6025257,12.183516","51.7333531,12.2172689","51.8452442,12.3273146","51.9514704,12.4555349","52.03493,12.6191926","52.1380019,12.7586353","52.227931,12.913034","52.3074102,13.0885363","52.4209106,13.1959963","52.5143051,13.3479595","52.5234738,13.4115041");

Я попробовал 2 подхода и потерпел неудачу.

1-й подход:

$cl = new SphinxClient;
$cl->SetLimits(0, 20);
$cl->SetMatchMode(SPH_MATCH_EXTENDED);

foreach($polylineLatLon as $singPoly){

     $singPolyExplode = explode(",",$singPoly);

     $latRad = Deg2Rad($singPolyExplode[0]);

     $LonRad = Deg2Rad($singPolyExplode[1]);

     $cl->SetGeoAnchor('latitude', 'longitude', $latRad,$LonRad);

     $cl->AddQuery("", $indexerName);
}
$result =$cl->runQueries();

Проблема с этим подходом в том, что он будет извлекать записи рядом с каждым геокодом. Не полный путь маршрута. Кроме того, расчет расстояния для каждой записи с помощью геокодирования ломаной линии займет много времени. Таким образом, это не оптимизированный подход.

2-й подход:

$cl = new SphinxClient;
$cl->SetLimits(0, 2000);
$cl->SetMatchMode(SPH_MATCH_EXTENDED);
$cl->SetSelect("*, CONTAINS(GEOPOLY2D(48.1390965,11.580255,48.2617271,11.6472244,48.3885849,11.5972817,48.5191226,11.5829265,48.6465704,11.516,48.773632,11.4611113,48.9037728,11.4703166,49.0096128,11.3544774,49.1298187,11.272155,49.2569017,11.2146807,49.3872571,11.2021279,49.5046949,11.2919927,49.6166182,11.3960946,49.7263312,11.5053892,49.8565686,11.51806,49.9767852,11.606766,50.0952959,11.6940558,50.2140534,11.7813241,50.3446984,11.7877614,50.4762554,11.8022454,50.6064391,11.791023,50.7318807,11.8482506,50.8638132,11.8523812,50.9891474,11.9091797,51.1166811,11.9561183,51.2372088,12.0594156,51.3430381,12.1846855,51.4732111,12.2154129,51.6025257,12.183516,51.7333531,12.2172689,51.8452442,12.3273146,51.9514704,12.4555349,52.03493,12.6191926,52.1380019,12.7586353,52.227931,12.913034,52.3074102,13.0885363,52.4209106,13.1959963,52.5143051,13.3479595,52.5234738,13.4115041), latitude_deg,longitude_deg) as inside");
$cl->setFilter("inside",array(1));
$result = $cl->Query("", $indexer);

Проблема с этим подходом заключается в том, что записи выбираются только внутри многоугольника. Однако мне нужны записи по обе стороны ломаной линии в пределах нескольких миль от маршрута.

enter image description here

1 Ответ

0 голосов
/ 11 мая 2020

В самом общем смысле, необходимо "буферизовать" полилинию, чтобы превратить ее в многоугольник :) Ie создать многоугольник, охватывающий область в пределах X расстояния от полилинии.

Buffer - хорошо известная операция ГИС. ... На самом деле я не знаю ни одной простой PHP библиотеки, которая будет это делать (у Sphinx ее нет!)

Google также создал алгоритм Route Boxer, который берет ломаную линию и превращается в серия неперекрывающихся прямоугольников. Этакая упрощенная (и более приближенная!) Система. Искать результаты для серии блоков проще, чем полные многоугольные запросы, даже если sphinx может их выполнять. Имеется PHP библиотека: https://github.com/bazo/route-boxer

...