[Mapserver-users] Point in polygon ?
Eric Bridger
eric at gomoos.org
Wed Oct 29 00:42:27 PST 2003
--=-UxW5cG3mjojAWQSuwjrO
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
On Tue, 2003-10-28 at 17:17, Stephen Clark wrote:
> Yes that would be nice.
>
> thanks,
> Stephen
>
The attached file contains Perl fragments and a map file fragment, just
to demonstrate my approach to determining which of a set of points is
inside of the polygons a user clicked. This is for Mapserver 3.6.
HTH,
Eric
--=-UxW5cG3mjojAWQSuwjrO
Content-Disposition: attachment; filename=polyquery.txt
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; name=polyquery.txt; charset=ISO-8859-15
# Perl mapscript for Mapserver 3.6
# Determine which of a set of points are contained in the polygons the user=
clicked on.
use CGI ":cgi";
# Map Server
use mapscript;
use XBase;
# A hash of points. we want to determine which of these points are in the p=
olygons clicked by the user.
my %points =3D (
ONE =3D>{'longitude' =3D> -67.0173,
'latitude' =3D> 44.8911,
},
TWO =3D>{'longitude' =3D> -66.0146,
'latitude' =3D> 45.2045,
},
THREE =3D>{'longitude' =3D> -68.3578,
'latitude' =3D> 43.7148,
},
FOUR =3D> {'longitude' =3D> -66.5528,
'latitude' =3D> 43.6243,
},
FIVE =3D>{'longitude' =3D> -68.9983,
'latitude' =3D> 44.0555,
},
SIX =3D>{'longitude' =3D> -67.8800,
'latitude' =3D> 43.4900,
},
SEVEN =3D>{'longitude' =3D> -70.5665,
'latitude' =3D> 42.5185,
},
);
# form input
my $q =3D new CGI;
my $map =3D new mapscript::mapObj('zone.map');
my ($lon, $lat) =3D get_click($q, $map);
my $click_pt =3D new mapscript::pointObj();
$click_pt->{x} =3D $lon;
$click_pt->{y} =3D $lat;
# this really should be a sub-routine.
my $layerObj =3D $map->getLayerByName('zones');
$layerObj->{status} =3D $mapscript::MS_ON;
# 1) Get all the polygons the user clicked.=20
$layerObj->queryByPoint($map,$clk_point,$mapscript::MS_MULTIPLE,undef);
# Open the dbf file. to get the polygon id. This is optional
my $dbfile =3D $layerObj->{data};
$dbfile .=3D '.dbf';
my $hDBF =3D new XBase "$dbfile" or warn XBase->errstr . "\n";
# 2) Open the shape file to get the shape polygon. must do after each quer=
yByPoint
if( $layerObj->open($layerObj->{data}) ){
warn "Could not open shapefile: $layerObj->{data}\n";
}
# the results go here
my @points_found =3D ();
my @polys_found =3D ();
my $results =3D $layerObj->{resultcache};
my $num_results =3D $results->{numresults};
# for each polygon in which the user clicked.
# Usually only 1 polygon has been clicked, but not always. Some of
# our zones overlap.
for my $i (0..$num_results-1){
my $rslt =3D $layerObj->getResult($i);
# shpidx is the record number in the polygon shape dbf file.
my $shpidx =3D $rslt->{shapeindex};
# Get the polygon id. This part is optional, but perhaps we want a list =
of
# points and the polygon ids they were in.
my @row =3D $hDBF->get_record_nf($shpidx, $fld) or warn $hDBF->errstr .=
"\n";
my $poly_id =3D $row[1];
# get the shape polygon
my $shape =3D new mapscript::shapeObj(-1);
if($layerObj->getShape($shape, undef, $shpidx)){
warn "Error in layer->getShape(): $shpidx\n";
next;=20
}
# 4) get the list of points contained in this polygon.
=09
my $point =3D new mapscript::pointObj(); # we re-use this point
foreach my $point_id ( keys %points) {
my $lat =3D sprintf("%.4f", $points{$point_id}{latitude});
my $lon =3D sprintf("%.4f", $points{$point_id}{longitude});
$point->{x} =3D $lon;
$point->{y} =3D $lat;
# Does the shape contain the point?
my $ret =3D $shape->contains($point);
if($ret =3D=3D 1){ # yes
push @points_found, $point_id;
push @polys_found, $poly_id;
}
} # end foreach point
} # end for num_results
$layerObj->close();
$hDBF->close();
############################################################
# SUBROUTINES
############################################################
# translate user click point (img.x and img.y) to lat/long
sub get_click {
my ($q, $map) =3D @_;
my @current_extent =3D ();
my($x_map, $y_map) =3D (0,0);
if($q->param('img.x') && $q->param('imgext')) { # Make sure we got a click
@current_extent =3D split(' ', $q->param('imgext'));
my $click_x =3D $q->param('img.x');
my $click_y =3D $q->param('img.y');
my $x_pct =3D ($click_x / $map->{width});
my $y_pct =3D 1 - ($click_y / $map->{height});
$x_map =3D $current_extent[0] + ( ($current_extent[2] - $current_extent[0=
]) * $x_pct);
$y_map =3D $current_extent[1] + ( ($current_extent[3] - $current_extent[1=
]) * $y_pct);
}
return ($x_map, $y_map);
}
############################################################
# MAP FILE FRAGMENT
############################################################
# zones
LAYER
NAME "zones"
TYPE POLYGON
STATUS OFF=20
DATA "../../data/mapserver/vector/zones"
TEMPLATE 'bogus.html'
TOLERANCE 1
CLASS
NAME "Zone"
OUTLINECOLOR 0 0 255=20
# to get thicker lines
SYMBOL 'circle'
SIZE 2
END # class
PROJECTION
"proj=3Dlatlong"
END
END # end zone layer
--=-UxW5cG3mjojAWQSuwjrO--
More information about the MapServer-users
mailing list