Need help with Layer->QueryByPoint
Jeff Portwine
jdport at VERITIME.COM
Mon Apr 4 09:20:09 PDT 2005
Thanks a lot for the response... that should get me going in the right
direction.
As for the bug you mentioned, can I work around that by simply adding the
layer to my map file and then opening it and adding the points via
mapscript? That way the layer isn't actually generated by mapscript, it's
only edited by mapscript... or would that cause the same problem?
Thanks again!
-Jeff
----- Original Message -----
From: "Camden Daily" <cdaily at GMAIL.COM>
To: <MAPSERVER-USERS at LISTS.UMN.EDU>
Sent: Monday, April 04, 2005 11:09 AM
Subject: Re: [UMN_MAPSERVER-USERS] Need help with Layer->QueryByPoint
> 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