# Query on location¶

To find data based on its geographical location, we can use the `location`

parameter of the search objects. This parameter takes a location filter expression as its argument, based on custom pydov location filters from the pydov.util.location module.

## Location filter predicates¶

A location query consists of a location filter predicate and a location. pydov uses custom location filter predicates and custom locations, all defined in the pydov.util.location module.

You can use the following location filters:

- Within
Search for points entirely within a given location. This does not include points on the boundary.

Example:

`Within(Box(200000, 211000, 205000, 214000))`

- Intersects
Search for points within or on the boundary of a given location.

Example:

`Intersects(Box(200000, 211000, 205000, 214000))`

- Touches
Search for points on the boundary but not inside a given location.

Example:

`Touches(Box(200000, 211000, 205000, 214000))`

- Disjoint
Search for points that don’t share any part with the given location. This means points that are completely outside of a polygon and its boundary.

Example:

`Disjoint(Box(200000, 211000, 205000, 214000))`

- Equals
Search for points exactly equal to the given location.

Example:

`Equals(Point(200000, 205000))`

A special location filter exists for spatial buffers, requiring a location and a distance:

- WithinDistance
Search for points within a given distance from a given location. By default, the distance is expressed in meters, but this can optionally by changed with the distance_unit parameter.

Example:

`WithinDistance(Point(200000, 205000), distance=100)`

Example:

`WithinDistance(location=Point(200000, 205000), distance=1, distance_unit='kilometer')`

## Using locations¶

You can define three different types of locations for use in a spatial filter: a rectangular box, a point and a custom GML object.

- Box
A rectangular twodimensional box defined by its lower left and upper right corners. The coordinate order for creating a Box is: lower left (minimum) x, lower left y, upper right (maximum) x, upper right y.

By default, boxes use the Belgian Lambert 72 coordinate reference system (EPSG:31370). Should you want to create a Box using GPS coordinates in decimal degrees, use the parameter epsg to change the coordinate reference system and enter the longitude range as minx and maxx and the latitude range as miny and maxy.

Example:

`Box(94720, 186910, 112220, 202870)`

Example:

`Box(3.6214, 50.9850, 3.8071, 51.1270, epsg=4326)`

- Point
A twodimensional point defined by its x and y coordinate.

By default, points use the Belgian Lambert 72 coordinate reference system (EPSG:31370). Should you want to create a Point using GPS coordinates in decimal degrees, use the parameter epsg to change the coordinate reference system and enter the longitude as x and the latitude y.

Example:

`Point(110680, 202030)`

Example:

`Point(3.8071, 51.1270, epsg=4326)`

- GmlObject
A custom GML 3.2 object. This can be any point, multipoint, linestring, multicurve (multilinestring), polygon or multisurface (multipolygon). This needs to be valid GML 3.2 for inclusion in the WFS 2.0.0 GetFeature request that pydov uses internally to query the datasets.

See also Using GML documents below.

with open('polygon.gml', 'r') as gmlfile: gml = gmlfile.read() gml_element = etree.fromstring(gml) gml_element = gml_element.find( './/{http://www.opengis.net/gml/3.2}Polygon') location = GmlObject(gml_element)

## Logically combining location filter expressions¶

The same way you can combine multiple attribute filters in one query, you can also combine different location filter in one location query. With the same logical filters from OWSLib you can build advanced spatial queries by using the And, Or and Not predicates from the owslib.fes2 package.

Each of And, Or and Not take a list as argument, in the case of And and Or the list should consist of at least two items. Each item can be a simple location filter expression, another And, Or or Not expression or a GmlFilter, so you can nest different levels of location filters.

- And
Return results that match all listed location filters.

Example:

`And([Within(Box(94720, 186910, 112220, 202870), WithinDistance(Point(94720, 186910), distance=200)])`

Example:

`And([Disjoint(Box(94720, 186910, 112220, 202870), Disjoint(Box(194720, 286910, 212220, 302870)])`

- Or
Return results that match one or more listed location filters.

Example:

`Or([Within(Box(94720, 186910, 112220, 202870), Within(Box(194720, 286910, 212220, 302870)])`

- Not
Return results that do not match any of the listed filters.

Example:

`Not([Intersects(GmlObject(gml_element))])`

## Using GML documents¶

To make it easy to use GML documents for spatial queries, there is a special location filter class for creating location filter expressions from GML documents: GmlFilter.

- GmlFilter
Build a location filter expression using a GML 3.2 document.

Instead of a single location filter, this class builds a location filter expression from a given GML document (gml), location filter (location_filter, optionally with location_filter_kwargs) and a logical combinator (by default this is Or).

Example: given a GML document containing polygons, this GmlFilter will return all results that are completely within

*any one*of the polygons (using the default Or combinator, the equivalent of a spatial union):GmlFilter('polygons.gml', Within)

Example: given a GML document containing polygons, this GmlFilter will return all results that are completely within

*all*of the polygons (using the And combinator, the equivalent of a spatial intersection):GmlFilter('polygons.gml', Within, combinator=And)

Example: given a GML document containing polygons (f.ex. Belgian communities), this GmlFilter will return all results that are completely disjoint from any of the polygons (i.e. are not inside of Belgium):

GmlFilter('polygons.gml', Disjoint, combinator=And)

Example: given a GML document containing linestrings, this GmlFilter will return all results that are within 500 meters of any one of the linestrings (using the default Or combinator, this is the equivalent of a spatial buffer followed by a spatial union):

GmlFilter('lines.gml', WithinDistance, {'distance': 500})

Example: given a GML document containing points, this GmlFilter will return all results that are within 5 kilometers of each of the points (using the And combinator, this is the equivalent of a spatial buffer followed by a spatial intersection):

GmlFilter('points.gml', WithinDistance, {'distance': 5, 'distance_unit': 'kilometer'}, combinator=And)

## Using other vector formats¶

To make it easy to use other vector formats for spatial queries, there is a special location filter class for creating location filter expressions from vector files: GeometryFilter.

This filter uses Fiona for reading the files and requires the fiona package to be installed. Check the Installation guide for details.

- GeometryFilter
Build a location filter expression using a vector document supported by Fiona.

Instead of a single location filter, this class builds a location filter expression from a given vector document (geometry), location filter (location_filter, optionally with location_filter_kwargs) and a logical combinator (by default this is Or).

Example: given a shapefile containing polygons, this GeometryFilter will return all results that are completely within

*any one*of the polygons (using the default Or combinator, the equivalent of a spatial union):GeometryFilter('polygons.shp', Within)

Example: given a shapefile containing polygons, this GeometryFilter will return all results that are completely within

*all*of the polygons (using the And combinator, the equivalent of a spatial intersection):GeometryFilter('polygons.shp', Within, combinator=And)

Example: given a shapefile containing polygons (f.ex. Belgian communities), this GeometryFilter will return all results that are completely disjoint from any of the polygons (i.e. are not inside of Belgium):

GeometryFilter('polygons.shp', Disjoint, combinator=And)

Example: given a shapefile containing linestrings, this GeometryFilter will return all results that are within 500 meters of any one of the linestrings (using the default Or combinator, this is the equivalent of a spatial buffer followed by a spatial union):

GeometryFilter('lines.shp', WithinDistance, {'distance': 500})

Example: given a shapefile containing points, this GeometryFilter will return all results that are within 5 kilometers of each of the points (using the And combinator, this is the equivalent of a spatial buffer followed by a spatial intersection):

GeometryFilter('points.shp', WithinDistance, {'distance': 5, 'distance_unit': 'kilometer'}, combinator=And)

## Using GeoPandas geodataframes¶

Integration with GeoPandas is available using the GeopandasFilter. It accepts a Geodataframe and builds a location filter out of it, ready to be used in a pydov query.

This filter uses Geopandas and requires the geopandas package to be installed. Check the Installation guide for details.

- GeopandasFilter
Build a location filter expression using a GeoPandas Geodataframe.

Instead of a single location filter, this class builds a location filter expression from a given Geodataframe (geodataframe), location filter (location_filter, optionally with location_filter_kwargs) and a logical combinator (by default this is Or).

Example: given a geodataframe containing polygons, this GeopandasFilter will return all results that are completely within

*any one*of the polygons (using the default Or combinator, the equivalent of a spatial union):GeopandasFilter(geodataframe, Within)

Example: given a geodataframe containing polygons, this GeopandasFilter will return all results that are completely within

*all*of the polygons (using the And combinator, the equivalent of a spatial intersection):GeopandasFilter(geodataframe, Within, combinator=And)

Example: given a geodataframe containing polygons (f.ex. Belgian communities), this GeopandasFilter will return all results that are completely disjoint from any of the polygons (i.e. are not inside of Belgium):

GeopandasFilter(geodataframe, Disjoint, combinator=And)

Example: given a geodataframe containing linestrings, this GeopandasFilter will return all results that are within 500 meters of any one of the linestrings (using the default Or combinator, this is the equivalent of a spatial buffer followed by a spatial union):

GeopandasFilter(geodataframe, WithinDistance, {'distance': 500})

Example: given a geodataframe containing points, this GeopandasFilter will return all results that are within 5 kilometers of each of the points (using the And combinator, this is the equivalent of a spatial buffer followed by a spatial intersection):

GeopandasFilter(geodataframe, WithinDistance, {'distance': 5, 'distance_unit': 'kilometer'}, combinator=And)