Need help with Layer->QueryByPoint

Camden Daily cdaily at GMAIL.COM
Mon Apr 4 11:09:27 EDT 2005


Jeff,

The first issue you're going to hit is a bug in mapscript that makes
the queryByPoint function useless against layers generated by
mapscript.  There's a fix in the CVS version of the code, but for now
just search the listserv archives for the terms 'queryByPoint' and
'index' to find some other threads regarding that bug.

As for queryByPoint, here's a function I wrote for getting the closest
points from a layer.  It may be overkill for your situation, but at
least it should demonstrate how queryByPoint works. It will return
multiple results in an array sorted by distance from the queried
point.  It also reprojects the points to a projection that uses meters
as units so that I can calculate a distance of miles instead of DD or
whatever.

Before you can query the layer, you'll need to set a template value
for your layer.  This doesn't need to be a real template, just
something to keep mapserver from complaining.  Just do something like
$layer->set("template", "dummy").

function get_closest($layer, $longitude, $latitude, $min_number_results) {
  global $map, $meter_to_mile;

  // create a new point object to test against
  $point = ms_newPointObj();
  $point->setXY($longitude, $latitude);

  $layer = $map->getLayerByName($layer);

  // toleranceunits do not need to be in the same units as the projections
  $layer->set("toleranceunits", MS_MILES);

  // loop through, increasing our search radius by 1 mile each time
until we find some matches
  $tolerance = 1;
  $max_tolerance = 30;  // won't search for points further than 30 miles away
  $found_flag = false;
  while (!$found_flag AND ($tolerance < $max_tolerance)) {
    $layer->set("tolerance", $tolerance);
    $layer->queryByPoint($point, MS_MULTIPLE, -1);
    $num_results = $layer->getNumResults();
    if ($num_results >= $min_number_results) {
      $found_flag = true; }
    else {
      $tolerance++; }
  }

  // if no results, return -1 to signify an error
  if ($num_results == 0) {
    return -1; }

  else {
    // clone the point
    $temp_point = ms_newPointObj();
    $temp_point->setXY($point->x, $point->y);

    // project cloned point to NAD83 / Illinois East so that our
calculated distance are in meters, not dd
    $temp_point->project(ms_newprojectionobj("init=epsg:4326"),
ms_newprojectionobj("init=epsg:26971"));

    // loop through our results and add them to our return array
    $layer->open();
    for ($i=0; $i < $num_results; $i++) {
      $result = $layer->getResult($i);
      $shape = $layer->getShape($result->tileindex, $result->shapeindex);
      // reproject our shape to the same projection as our cloned point
      $shape->project(ms_newprojectionobj("init=epsg:4326"),
ms_newprojectionobj("init=epsg:26971"));
      $distance = $temp_point->distanceToShape($shape);
      $distance = round($distance * $meter_to_mile, 2);
      // add the data to our array
      $return[$i]['distance'] = $distance;
      $return[$i]['shape'] = $shape;
    }
    $layer->close();

    // sort our multidimensional array on 'distance'
    foreach ($return as $val) {
      $sortarray[] = $val['distance']; }
    array_multisort($sortarray, $return);

    return $return;
  }
}



More information about the mapserver-users mailing list