[mapserver-users] QuerybyPoint blues

Hankley, Chip Chip.Hankley at gasai.com
Wed Oct 2 10:17:41 EDT 2002


Guys...

The query function that I use is below... the mapfile definition is quite
simple... note the TEMPLATE line.

LAYER
  NAME "ZIP"
  DATA "Vector\Rock_ZIP"
  TEMPLATE "ttt_query.html" #Important Line!
  STATUS OFF
  TYPE POINT
  CLASS
    COLOR 255 0 0
  END
END


The variables being passed are:
$map - the map object
$coords - the coordinates (image coordinates) of the click
$Last_Extent - the map extent (map coordinates)
$lyr_name - the name of the layer in the mapfile

There are several things to note about this function.
  1) You don't have to specify RESULT FIELDS in the metadata. 
     It returns everything from the dbase record.
  2) One thing I found w/ querybypoint was that if I wanted
     to query a layer that was lower in the drawing order (i.e.
     it was on the bottom), I would often get the "no records
     returned" error... even when I was OBVIOUSLY clicking right
     on the object. What this function does is turn all of the
     layers that you are not querying off before doing the query
     then turns them back on at the end. The result is that I get
     much more consistent query results. The end user never sees
     the "on" and "off" of the layers... it just happens on either
     side of the query.

Use the print_r function in PHP to examine the results of the function. The
variable $result is a multi-dimensional array. The code now does MS_SINGLE,
but it could just as easily do MS_MULTIPLE. You could also change this
easily to do a querybypoint or rectangle, depending on what $coords look
like when they are passed.

Cheers!

Chip Hankley
 


function query_map($map, $coords, $Last_Extent, $lyr_name) {
  //First, loop through all the layers, making an associative
  // array of how they are currently set. We are going to then
  // turn all of the layers off. Later (a few lines down) we
  // will turn the query layer on. At the end of the function,
  // we will turn the ON layers back on.
  $onLayers = array();
  foreach ($map->getAllLayerNames() as $a) {
    $Layer = $map->GetLayerByName($a);
    if ($Layer->status) {
      array_push($onLayers, $a);
      $Layer->set("status",0);
    }
  }

  //Get the Layer being queried
  $Layer = $map->GetLayerByName("$lyr_name");
  $data_nm = $Layer->data;
  $data_pth = $map->shapepath;
  $shpPath = $data_pth . $data_nm;
  
  //Set the layers status ON (b/c it might not be...)
  $Layer->set("status", 1);

  //Convert Image Coords to Map Coords
  $rect_coords = explode(";", $coords);
  $ll_coord = explode(",", $rect_coords[0]);

  $ImgWidth = $map->width;
	$ImgHeight = $map->height;
  $x = (($ll_coord[0] / $ImgWidth) * ($Last_Extent[2] - $Last_Extent[0])) +
$Last_Extent[0];
  $y = $Last_Extent[3] - (($ll_coord[1] / $ImgHeight) * ($Last_Extent[3] -
$Last_Extent[1]));

  $click_pt = ms_newPointObj();
  $click_pt->setXY($x, $y);
  
  //Query the Map at the point clicked
  @$map->queryByPoint($click_pt, MS_SINGLE, -1);
  $count_results = $Layer->getNumResults();
  

  if ($count_results > 0) {
    $Layer->open($map->shapepath);
    $result=array();

    //create a dynamic layer in which to display the selectd record
    $qryLyr = ms_newLayerObj($map);
    $qryLyr->set("status", MS_ON);
    $qryLyr->set("name", "Temporary Query Layer");
    $qryLyr->set("type", $Layer->type);
      $qryLyrClass = ms_newClassObj($qryLyr);
      $qryLyrClass->set("color", $map->addColor(255, 0 ,0));
      //set the type and size
      if ($Layer->type==0) { //Point
        $qryLyrClass->set("symbol", 7);
        $qryLyrClass->set("size", 18);
      }
      elseif ($Layer->type==1) { //Line
        $qryLyrClass->set("symbol", 2);
        $qryLyrClass->set("size", 3);
      }
      elseif ($Layer->type==2) { //Polygon
        $qryLyrClass->set("symbol", 1);
        $qryLyrClass->set("size", 2);
      }

    //get the names of the fields in the shapefile
    if ($dbi = dbase_open($shpPath . ".dbf", 0)) {
      $db_fields = array_keys(dbase_get_record_with_names ($dbi, 1));
      dbase_close($dbi);
      //the SHAPE field is returned as 'delelted', so use
      //  a callback function to remove it.
      $db_fields = array_filter($db_fields, "ResultFieldFilter");
    }

    for ($i=0; $i<= $count_results-1; $i++) {
      $oRes = $Layer->getResult($i);
      $oShape = $Layer->getShape($oRes->tileindex,$oRes->shapeindex);
      $temp=array();
      foreach($db_fields as $a) {
        $tRes = $oShape->values[$a];
        if ($tRes == "") {
          $tRes = "&nbsp;";
        }
        $temp[$a] = $tRes;
      }
      $result[$i] = $temp;
      unset ($temp);

      //Move the $oShape and $qryLyr variable to
      // global scope to be called before drawing
      // the map      
      $GLOBALS["oShape"] = $oShape;
      $GLOBALS["qryLyr"] = $qryLyr;
    }
  }
  else $result = "No records returned";
  
  //Turn the query layer off, then turn all of
  // the layers that were on, back on
  $Layer->set("status", 0);
  foreach ($onLayers as $a) {
    $Layer = $map->GetLayerByName($a);
    $Layer->set("status",1);
  }
  
  return $result;
}
//Callback function to remove the 'deleted' value that
// is returned for the SHAPE field
function ResultFieldFilter($var) {
  return($var <> 'deleted');
}



More information about the mapserver-users mailing list