Как нарисовать многоугольник MySQL, а не квадрат? - PullRequest
0 голосов
/ 01 декабря 2009

Функция ниже создает многоугольник из 4 точек, и я предполагаю, что последняя 5-я точка закрыла квадрат, мне нужно, чтобы она имела как минимум 24 точки и составляла круг. Есть идеи?

function getRadius($point="POINT(-29.8368 30.9096)", $radius=2)
{
    $km = 0.009;
    $center = "GeomFromText('$point')";
        $radius = $radius*$km;
        $bbox = "CONCAT('POLYGON((',
                X($center) - $radius, ' ', Y($center) - $radius, ',',
                X($center) + $radius, ' ', Y($center) - $radius, ',',
                X($center) + $radius, ' ', Y($center) + $radius, ',',
                X($center) - $radius, ' ', Y($center) + $radius, ',',
                X($center) - $radius, ' ', Y($center) - $radius, '
        ))')";

    $query = $this->db->query("
        SELECT id, AsText(latLng) AS latLng, (SQRT(POW( ABS( X(latLng) - X({$center})), 2) + POW( ABS(Y(latLng) - Y({$center})), 2 )))/0.009 AS distance
        FROM crime_listing
        WHERE Intersects( latLng, GeomFromText($bbox) )
        AND SQRT(POW( ABS( X(latLng) - X({$center})), 2) + POW( ABS(Y(latLng) - Y({$center})), 2 )) < $radius
        ORDER BY distance
                ");

    if($query->num_rows()>0){
                return($query->result());
        }else{
                return false;
        }
}

Ниже версии js, и это прекрасно работает

var findCirclePolygons = function(point, r)
{   
    var d2r = Math.PI / 180;
    this.circleLatLngs = new Array();
    numPoints = 24;
    var circleLat = r * 0.009;  // Convert degrees into km
    var circleLng = circleLat / Math.cos(point.lat() * d2r);
    for (var i = 0; i < numPoints + 1; i++) {
        var theta = Math.PI * (i / (numPoints / 2));
        var vertexLat = point.lat() + (circleLat * Math.sin(theta));
        var vertexLng = parseFloat(point.lng()) + parseFloat(( circleLng * Math.cos(theta)));
        var vertextLatLng = new google.maps.LatLng(vertexLat, vertexLng);
        this.circleLatLngs.push(vertextLatLng);
    }

    // Set options
    var options = {
        paths: circleLatLngs,
        strokeColor: "#0055ff",
        strokeOpacity: 1,
        strokeWeight: 1,
        fillColor: "#0055ff",
        fillOpacity: 0.35
        };

    // Return
    return options;
};

1 Ответ

2 голосов
/ 01 декабря 2009

Вы можете сделать цикл (в псевдокоде):

for(i=0; i <= 360; i += 360/24)
{
    $extra_point = "POINT(". $radius*cos(i)." ". $radius*sin(i) . ")"
}

EDIT

  • Однако, если вы просто хотите ограничивающий прямоугольник, тогда использование квадрата - правильный способ сделать это. Не нужно иметь ограничивающую рамку, выглядящую как круг. Вы отфильтруете позже с сортировкой.
  • Для измерения расстояния не нужно использовать ABS. Квадрат делает это за вас (дополнительно, сравните с радиусом в квадрате вместо вычисления квадратного корня, если вы крайне требовательны к производительности
  • Не забудьте добавить пространственный индекс, иначе спектакли будут дерьмовыми

2-е РЕДАКТИРОВАНИЕ В несколько меньшем количестве псевдокода;) (я давно не работал с php).

$lon = 42;
$lat = 2;
$radius = 0.01;
$bbox = "POLYGON((";
for(i=0; i <= 360; i += 360/24)
{
    $bbox .= $radius*cos(deg2rad(i)) + $lon." ". $radius*sin(deg2rad(i)) + $lat;
    if(i < 360)"
        $bbox .= ", "
}
$bbox .= "))"

Что касается расстояния, у вас есть pow (abs (x), 2) == pow (x, 2) для любого x. Так что вы можете просто написать (для простоты):

SQRT(POW( X(latLng) - X({$center}), 2) + POW(Y(latLng) - Y({$center}), 2 )) < $radius

Или даже сэкономить вычисление квадратного корня (в этом случае оно абсолютно ничего не изменит, и ранняя оптимизация - это плохо, так что делайте, как хотите)

POW( X(latLng) - X({$center}), 2) + POW(Y(latLng) - Y({$center}), 2 ) < POW($radius, 2)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...