views:

497

answers:

1

The function below creates a polygon square out of 4 points and I assume the last 5th point closed the squar, I need it to have at least 24 points and to make up a circle. Any ideas?

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;
        }
}

Below the the js version and this works perfect

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;
};
A: 

You can make a loop (in pseudo code):

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

EDIT

  • However, if you just want a bounding box, then using a square is the right way to do it. No need to have a circle looking bounding box. You filter out later with the sorting.
  • To measure the distance, no need to use ABS. Squaring does it for you (as an extra, compare to the radius squared instead of computing the square root if you are extreamly picky about performances
  • Don't forget to add the spatial index or the performances will be crap

2nd EDIT In somewhat less pseudo-code ;) (It's been ages I didn't work with 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 .= "))"

About the distance thing, you have pow(abs(x),2) == pow(x, 2) for any x. So you can just write (for simplicity):

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

Or even to spare the computation of the square root (in this case it won't change absolutely anything and early optimization is a bad thing, so do as you whish)

POW( X(latLng) - X({$center}), 2) + POW(Y(latLng) - Y({$center}), 2 ) < POW($radius, 2)
Tristram Gräbener
Hi, thanks for the help, except I need the "$bbox" to be the "circle". But I do see what you mean by the bounding box and filtering out the extra points, I'm going to give it a try. thanks for your help.
Derrick
Thanks again for your help, Im going to give this another try.
Derrick