Add support for distance filter for the marker layer.

This commit is contained in:
David Molineus
2018-10-30 10:48:38 +01:00
parent 314e2d21ee
commit 2108de32d9
4 changed files with 74 additions and 13 deletions

View File

@@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
- Custom route to load map data. - Custom route to load map data.
- Add distance filter support for the marker layer (Bounds Mode "fit" has to be enabled).
### Deprecated ### Deprecated

View File

@@ -93,4 +93,24 @@ class DistanceFilter implements Filter
'center' => $this->center, 'center' => $this->center,
]; ];
} }
/**
* Get the center coordinate.
*
* @return LatLng
*/
public function getCenter(): LatLng
{
return $this->center;
}
/**
* Get the distance radius.
*
* @return int
*/
public function getRadius(): int
{
return $this->radius;
}
} }

View File

@@ -185,7 +185,7 @@ class MarkersLayerMapper extends AbstractLayerMapper implements GeoJsonMapper
{ {
$repository = $this->repositoryManager->getRepository(MarkerModel::class); $repository = $this->repositoryManager->getRepository(MarkerModel::class);
if ($model->boundsMode == 'fit') { if ($model->boundsMode === 'fit') {
return $repository->findByFilter($model->id, $request->getFilter()); return $repository->findByFilter($model->id, $request->getFilter());
} }

View File

@@ -12,9 +12,12 @@
namespace Netzmacht\Contao\Leaflet\Model; namespace Netzmacht\Contao\Leaflet\Model;
use Contao\Model\Collection;
use Netzmacht\Contao\Leaflet\Filter\BboxFilter; use Netzmacht\Contao\Leaflet\Filter\BboxFilter;
use Netzmacht\Contao\Leaflet\Filter\DistanceFilter;
use Netzmacht\Contao\Leaflet\Filter\Filter; use Netzmacht\Contao\Leaflet\Filter\Filter;
use Netzmacht\LeafletPHP\Value\LatLngBounds; use Netzmacht\LeafletPHP\Value\LatLngBounds;
use function var_dump;
/** /**
* Class MarkerModel for the tl_leaflet_marker table. * Class MarkerModel for the tl_leaflet_marker table.
@@ -34,20 +37,23 @@ class MarkerModel extends AbstractActiveModel
* Find by a filter. * Find by a filter.
* *
* @param int $pid The parent id. * @param int $pid The parent id.
* @param Filter $filter The filter. * @param Filter|null $filter The filter.
* *
* @return \Contao\Model\Collection|null * @return Collection|null
*/ */
public static function findByFilter($pid, Filter $filter = null) public static function findByFilter($pid, ?Filter $filter = null)
{ {
if (!$filter) { if (!$filter) {
return static::findActiveBy('pid', $pid, ['order' => 'sorting']); return static::findActiveBy('pid', $pid, ['order' => 'sorting']);
} }
switch ($filter->getName()) { switch (true) {
case 'bbox': case $filter instanceof BboxFilter:
return static::findByBBoxFilter($pid, $filter); return static::findByBBoxFilter($pid, $filter);
case $filter instanceof DistanceFilter:
return static::findByDistanceFilter($pid, $filter);
default: default:
return null; return null;
} }
@@ -59,15 +65,16 @@ class MarkerModel extends AbstractActiveModel
* @param int $pid The layer id. * @param int $pid The layer id.
* @param BboxFilter $filter The bbox filter. * @param BboxFilter $filter The bbox filter.
* *
* @return \Contao\Model\Collection|null * @return Collection|null|MarkerModel[]
*/ */
public static function findByBBoxFilter($pid, BboxFilter $filter) public static function findByBBoxFilter($pid, BboxFilter $filter)
{ {
$table = static::getTable();
$columns = [ $columns = [
'active=1', $table . '.active=1',
'pid=?', $table . '.pid=?',
'latitude > ? AND latitude < ?', $table . '.latitude > ? AND ' . $table . '.latitude < ?',
'longitude > ? AND longitude < ?', $table . '.longitude > ? AND ' . $table . '.longitude < ?',
]; ];
/** @var LatLngBounds $bounds */ /** @var LatLngBounds $bounds */
@@ -80,6 +87,39 @@ class MarkerModel extends AbstractActiveModel
$bounds->getNorthEast()->getLongitude(), $bounds->getNorthEast()->getLongitude(),
]; ];
return static::findBy($columns, $values, ['order' => 'sorting']); return static::findBy($columns, $values, ['order' => $table . '.sorting']);
}
/**
* Find marker by distance filter.
*
* @param int $pid The layer id.
* @param DistanceFilter $filter THe distance filter.
*
* @return Collection|null|MarkerModel[]
*/
public static function findByDistanceFilter($pid, DistanceFilter $filter): ?Collection
{
$table = static::getTable();
$query = <<<SQL
round(
sqrt(
power( 2 * pi() / 360 * (? - {$table}.latitude) * 6371,2)
+ power( 2 * pi() / 360 * (? - {$table}.longitude) * 6371 * COS( 2 * pi() / 360 * (? + {$table}.latitude) * 0.5 ),2)
)
) <= ?
SQL;
$center = $filter->getCenter();
$latitude = $center->getLatitude();
$longitude = $center->getLongitude();
$values = [$pid, $latitude, $longitude, $latitude, $filter->getRadius()];
$columns = [
$table . '.active=1',
$table . '.pid=?',
$query
];
return static::findBy($columns, $values, ['order' => $table . '.sorting']);
} }
} }