# Spatial Operators

We will have a look at some Spatial Operators now. Remember what we saw in GetCapabilities:

```xml
<fes:SpatialOperators>
   <fes:SpatialOperator name="BBOX"/>
   <fes:SpatialOperator name="Equals"/>
   <fes:SpatialOperator name="Disjoint"/>
   <fes:SpatialOperator name="Intersects"/>
   <fes:SpatialOperator name="Touches"/>
   <fes:SpatialOperator name="Crosses"/>
   <fes:SpatialOperator name="Within"/>
   <fes:SpatialOperator name="Contains"/>
   <fes:SpatialOperator name="Overlaps"/>
   <fes:SpatialOperator name="Beyond"/>
   <fes:SpatialOperator name="DWithin"/>
</fes:SpatialOperators>
```

As we are using the **FeatureReader**, you may ask yourself: FeatureReader comes with predefined **Spatial Filters**, so why should I look into Spatial Filter Expressions?

<figure><img src="https://60501452-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFgBfA6ZqJjyopUS8Ss5Q%2Fuploads%2F2A7eWWCTr1fgMAimP3D2%2Ffr01.png?alt=media&#x26;token=17bcfaef-22bb-41de-86b4-987f018bc318" alt=""><figcaption><p>Spatial Filters in FeatureReader</p></figcaption></figure>

The answer is: Yes, the Spatial Filters listed above are working in most cases, but they don't use XML Filter Expressions!

Let's consult our best friend the Translation Log. To do so, you may use the following lightweight Workbench.

| Parameter      | Value                                                       |
| -------------- | ----------------------------------------------------------- |
| WFS URL        | <https://www.wfs.nrw.de/geobasis/wfs_nw_alkis_vereinfacht?> |
| Version        | 2.0                                                         |
| Features Types | **Flurstueck** (cadastral parcel)                           |
| Max Features   | leave blank                                                 |

<figure><img src="https://60501452-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFgBfA6ZqJjyopUS8Ss5Q%2Fuploads%2FH1oEoT6Y7Wd8GYbCH5OH%2Fwfs_026.png?alt=media&#x26;token=c37c18d2-dff2-4da0-baa2-0f2222cee7a7" alt=""><figcaption></figcaption></figure>

{% file src="<https://60501452-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFgBfA6ZqJjyopUS8Ss5Q%2Fuploads%2FZKhqqOfp5t442jTJyeID%2Fpostalcodes_nw.geojson?alt=media&token=0d93d033-3baa-4cb7-bcb9-78103eb11b0c>" %}
Some postal code polygons
{% endfile %}

{% file src="<https://60501452-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFgBfA6ZqJjyopUS8Ss5Q%2Fuploads%2Fxpau0v6GpgMJirbLH3vR%2Fspatial_filtering_01_fme2022.fmw?alt=media&token=c9cee8a7-c076-4645-bbf8-102d9d15c4bb>" %}

Select a Spatial Filter of your choice (**except OGC-Disjoint**), run the Workbench, switch to Translation Log and look for the already known

```
<WFS> GetFeature URL:
```

You'll find a really long URL like this&#x20;

<figure><img src="https://60501452-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFgBfA6ZqJjyopUS8Ss5Q%2Fuploads%2F0FFrv1yLcsDMn7574SXp%2Fwfs_027.png?alt=media&#x26;token=391c3890-8878-4421-9b5c-5db549d6dbca" alt=""><figcaption></figcaption></figure>

And the most interesting thing is this

<figure><img src="https://60501452-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFgBfA6ZqJjyopUS8Ss5Q%2Fuploads%2Fdf6RJVZyAz8VMx4vNv3x%2Fwfs_028.png?alt=media&#x26;token=db54b712-c065-4a53-91d8-d326c4a108b5" alt=""><figcaption></figcaption></figure>

<mark style="color:green;">**&**</mark>**BBOX**=xmin,ymin,xmax,ymax,urn:ogc:def:crs:EPSG::25832<mark style="color:green;">**&**</mark>

According to OGC WFS specification, you may also pass a Bounding Box (BBOX) as **URL Parameter** (see ampersands <mark style="color:green;">**&**</mark>) to the WFS service.

| Spatial Filter                            | Request               | Notice                                                   |
| ----------------------------------------- | --------------------- | -------------------------------------------------------- |
| **Bounding Boxes** OGC-Intersect          | BBOX as URL Parameter |                                                          |
| Initiator OGC-**Intersects** Result       | BBOX as URL Parameter |                                                          |
| Initiator OGC-**Contains** Result         | BBOX as URL Parameter |                                                          |
| Initiator OGC-**Crosses** Result          | BBOX as URL Parameter |                                                          |
| Initiator is OGC-**Disjoint** from Result | No filter             | get's max. number of features and may run into a timeout |
| Initiator OCG-**Equals** Result           | BBOX as URL Parameter |                                                          |
| Initiator OGC-**Overlaps** Result         | BBOX as URL Parameter |                                                          |
| Initiator OGC-**Touches** Result          | BBOX as URL Parameter |                                                          |
| Initiator is OGC-**Within** Result        | BBOX as URL Parameter |                                                          |

**What does this mean?**

This means, that the FeatureReader sends a BBOX to the WFS and does the spatial filtering within this BBOX locally, which means inside FME itself (**client-side**).

That's generally ok, but as we are dealing with **Filter Expressions** where the WFS service does the filtering **server-side**, we will have a look, what's possible using XML Filter Expressions.

Let's return to our already known INSPIRE cadastral parcel WFS.

| Parameter      | Value                                                                                              |
| -------------- | -------------------------------------------------------------------------------------------------- |
| WFS URL        | <https://www.wfs.nrw.de/geobasis/wfs_nw_inspire-flurstuecke_alkis?>                                |
| Version        | 2.0                                                                                                |
| Features Types | CadastralParcel                                                                                    |
| Max Features   | leave blank                                                                                        |
| xmlns          | <p>gml="<http://www.opengis.net/gml/3.2>"<br>cp="<http://inspire.ec.europa.eu/schemas/cp/4.0>"</p> |

## BBOX

The BBOX is the most powerful filter. It's a real swiss army knife!\
Not without good reason the FeatureReader uses a Bounding Box (BBOX) for spatial filtering.

You may paste the following Filter Expression into a WFS Reader

```xml
<fes:Filter
	xmlns:fes="http://www.opengis.net/fes/2.0"
	xmlns:gml="http://www.opengis.net/gml/3.2">
  <fes:BBOX>
        <gml:Envelope srsName="urn:ogc:def:crs:EPSG::25832">
          <gml:lowerCorner>367441.62 5620100.532</gml:lowerCorner>
          <gml:upperCorner>367619.15 5620254.767</gml:upperCorner>
       </gml:Envelope>
   </fes:BBOX>
</fes:Filter>
```

but we'll skip that step.

Utilize **Creator** instead to build a BBOX using the coordinates shown above.&#x20;

<figure><img src="https://60501452-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFgBfA6ZqJjyopUS8Ss5Q%2Fuploads%2FvVddvbEHHG5BfGNBBKmZ%2Fwfs_029.png?alt=media&#x26;token=2988df80-f3f6-46aa-a27d-a71cb662df7c" alt=""><figcaption></figcaption></figure>

Set the Coordinate System to EPSG:25832 and fetch the Coordinates (xmin, ymin, xmax, ymax) with **BoundsExtractor**.&#x20;

<figure><img src="https://60501452-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFgBfA6ZqJjyopUS8Ss5Q%2Fuploads%2F09W6SsaobJj81nvERghe%2Fwfs_030.png?alt=media&#x26;token=ca2eae70-c030-455c-a929-444d4cae6757" alt="" width="365"><figcaption></figcaption></figure>

Color the outline of the BBOX (**FeatureColorSetter**) and connect the **Inspector**.

Insert a **FeatureReader**, configure the WFS connection as shown above and paste the following Filter Expression

```xml
<fes:Filter
	xmlns:fes="http://www.opengis.net/fes/2.0"
	xmlns:gml="http://www.opengis.net/gml/3.2">
  <fes:BBOX>
        <gml:Envelope srsName="urn:ogc:def:crs:EPSG::25832">
          <gml:lowerCorner>@Value(xmin) @Value(ymin)</gml:lowerCorner>
          <gml:upperCorner>@Value(xmax) @Value(ymax)</gml:upperCorner>
       </gml:Envelope>
   </fes:BBOX>
</fes:Filter>
```

<figure><img src="https://60501452-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFgBfA6ZqJjyopUS8Ss5Q%2Fuploads%2FpsQQnFdgIAcdcDDqRmfi%2Fwfs_031.png?alt=media&#x26;token=544e8ad7-4203-434b-aff7-18e4aebb4e1a" alt=""><figcaption></figcaption></figure>

As you can see, it get's the BBOX corner coordinates dynamically as well.

Connect the FeatureReader also with the **Inspector** and run the Workbench.

<figure><img src="https://60501452-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFgBfA6ZqJjyopUS8Ss5Q%2Fuploads%2F71SywcDDCRjL7GTO4DNk%2Fwfs_032.png?alt=media&#x26;token=fcf79ae6-dcfd-4f63-ae9a-ffde5c2d4316" alt=""><figcaption></figcaption></figure>

<figure><img src="https://60501452-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFgBfA6ZqJjyopUS8Ss5Q%2Fuploads%2F9kH8VeW6FDUhZW1M7y3w%2Fwfs_033.png?alt=media&#x26;token=b4e2b133-3565-469d-a2d4-aadb0ebac47a" alt=""><figcaption></figcaption></figure>

The BBOX Filter **selects** all **features**, that are **touched by** the **BBOX on the WFS server (server-side)**. So far so good.

But what's the magic?

Imagine, you don't know the cadastral parcel number(s) of the parcel(s) you need. For this reason you can't do the attributive query we've seen before (see [1st Filter](https://olivers-expression-lab.gitbook.io/filter-expressions-in-fme/1st-filter)).

But you've postal addresses instead and you are able to geocode them, i.e. you know the xy-coordinates of the address point, e.g.

```
Address:             Platz der Vereinten Nationen 2, 53113 Bonn
XY-Coords (UTM32N):  367591.0 5620196.0   
```

If so

* [ ] just create a point (**Creator** or **VertexCreator** in case of a list)
* [ ] with a small buffer, let's say 0,5 m (**Bufferer**)
* [ ] fetch the BBOX (xmin, ymin, xmax, ymax) (**BoundsExtractor**)
* [ ] and pipe the values into into the BBOX Filter Expression (**FeatureReader**) as shown above

Tadaa: what's the result?

We got our already known cadastral parcel 05430202600946\_\_\_\_\_\_, this time using a Spatial Filter Expression.

<figure><img src="https://60501452-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFgBfA6ZqJjyopUS8Ss5Q%2Fuploads%2FjUzxl5egDiA2Dlg2LeTj%2Fwfs_034.png?alt=media&#x26;token=2e913d2a-d1bd-4c8b-93a6-6172b71e2966" alt=""><figcaption></figcaption></figure>

As you can replace nearly any geometry by its BBOX, now you know how to use it, either by a&#x20;

* BBOX Filter Expression or
* FMEs built-in BBOX Filter

For the sake of completeness, we will have a look at some other Spatial Operators.

<mark style="color:green;">Please keep in mind, that the</mark> <mark style="color:green;"></mark><mark style="color:green;">**filtering**</mark> <mark style="color:green;"></mark><mark style="color:green;">is done</mark> <mark style="color:green;"></mark><mark style="color:green;">**server-side**</mark> <mark style="color:green;"></mark><mark style="color:green;">when</mark> <mark style="color:green;"></mark><mark style="color:green;">**using XML Filter Expressions**</mark><mark style="color:green;">!</mark>

{% file src="<https://60501452-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFgBfA6ZqJjyopUS8Ss5Q%2Fuploads%2FL423P8md6o4rdRDEfdhm%2Fspatial_filtering_BBOX_Within_fme2022.fmw?alt=media&token=923468de-0a3a-4939-9348-5992a19886e0>" %}

## Within

In contrast to BBOX, **Within** only filters the features, which are **completely within** **the** bounding **box**.

```xml
<fes:Filter
	xmlns:fes="http://www.opengis.net/fes/2.0"
	xmlns:gml="http://www.opengis.net/gml/3.2">
  <fes:Within>
        <gml:Envelope srsName="urn:ogc:def:crs:EPSG::25832">
          <gml:lowerCorner>367441.62 5620100.532</gml:lowerCorner>
          <gml:upperCorner>367619.15 5620254.767</gml:upperCorner>
       </gml:Envelope>
   </fes:Within>
</fes:Filter>
```

We use a bounding box which fits the large green polygon, but as you can see an additional polygon is returned, see top right.

<figure><img src="https://60501452-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFgBfA6ZqJjyopUS8Ss5Q%2Fuploads%2FuZ1IZ0KVGyHY2RShDVCi%2Fwithin.png?alt=media&#x26;token=03d3a5ed-8f5f-4c8f-88a8-201cb2f3d7b2" alt=""><figcaption></figcaption></figure>

## DWithin

**DWithin** uses a radius (circle) defined by

* a **center point** - don't forget to secifiy the **S**patial **R**eference **S**ystem aka coordinate system in **srsName**, check [GetCapabilities](https://olivers-expression-lab.gitbook.io/filter-expressions-in-fme/getcapabilities) which are supported by your WFS
* a **distance** - please check, if the **U**nit **o**f **M**easure (**uom**) fits to your needs

```xml
<fes:Filter
	xmlns:fes="http://www.opengis.net/fes/2.0"
	xmlns:gml="http://www.opengis.net/gml/3.2"
	xmlns:cp="http://inspire.ec.europa.eu/schemas/cp/4.0">
   <fes:DWithin>
      <fes:ValueReference>cp:geometry</fes:ValueReference>
      <gml:Point srsName="urn:ogc:def:crs:EPSG::25832">
        <gml:coordinates>367527.734,5620177.942</gml:coordinates>
      </gml:Point>
      <fes:Distance uom='m'>2000</fes:Distance>
   </fes:DWithin>
</fes:Filter>
```

The WFS returns all features within the defined search radius.

<figure><img src="https://60501452-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FFgBfA6ZqJjyopUS8Ss5Q%2Fuploads%2F0LdpAW0Xga7geQzARLxz%2Fdwithin.png?alt=media&#x26;token=bca201d0-03f2-476c-bab8-358be0ee8f9a" alt=""><figcaption></figcaption></figure>

## Spatial Filtering using more than a rectangle

*Yes, it's possible!*&#x20;

*I'm preparing an example. Stay tuned and come back!*


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://olivers-expression-lab.gitbook.io/filter-expressions-in-fme/spatial-operators.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
