Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/mkeller3/FastVector
A PostGIS based Vector Tile server with caching and filtering.
https://github.com/mkeller3/FastVector
asyncpg fastapi leaflet mapbox mapbox-vector-tile maplibre postgis postgres postgresql python tile-server tiles vector-tiles
Last synced: 3 months ago
JSON representation
A PostGIS based Vector Tile server with caching and filtering.
- Host: GitHub
- URL: https://github.com/mkeller3/FastVector
- Owner: mkeller3
- License: mit
- Created: 2022-06-23T00:56:06.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2022-07-08T21:06:36.000Z (almost 2 years ago)
- Last Synced: 2024-01-17T06:47:40.878Z (5 months ago)
- Topics: asyncpg, fastapi, leaflet, mapbox, mapbox-vector-tile, maplibre, postgis, postgres, postgresql, python, tile-server, tiles, vector-tiles
- Language: Python
- Homepage:
- Size: 122 KB
- Stars: 34
- Watchers: 2
- Forks: 4
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Lists
- awesome-vector-tiles - FastVector - is a multi database PostGIS based vector tile server with cql filtering and caching written in [Python](https://www.python.org/) with [FastAPI](https://fastapi.tiangolo.com/). Inspired by TiMVT. (Servers / Applications / Command line tools)
README
# FastVector
FastVector is a [PostGIS](https://github.com/postgis/postgis) [vector tiles](https://github.com/mapbox/vector-tile-spec) built for serving large geometric tables. FastVector is written in [Python](https://www.python.org/) using the [FastAPI](https://fastapi.tiangolo.com/) web framework.
FastVector is built with inspriration from [TiMVT](https://github.com/developmentseed/timvt).
It defers from TiMVT in the fact that it has multi server/database support, cql_filtering, and a fields parameter.
---
**Source Code**: https://github.com/mkeller3/FastVector
---
## Requirements
FastVector requires PostGIS >= 2.4.0.
## Configuration
In order for the api to work you will need to edit the `config.py` file with your database connections.
Example
```python
DATABASES = {
"data": {
"host": "localhost", # Hostname of the server
"database": "data", # Name of the database
"username": "postgres", # Name of the user, ideally only SELECT rights
"password": "postgres", # Password of the user
"port": 5432, # Port number for PostgreSQL
"cache_age_in_seconds": 6000, # Number of seconds for tile to be cache in clients browser. You can set to zero if you do not want any caching.
"max_features_per_tile": 100000 # Maximum features per tile. This helps with performance for tables with a large number of rows.
}
}
```## Usage
### Running Locally
To run the app locally `uvicorn main:app --reload`
### Production
Build Dockerfile into a docker image to deploy to the cloud.## API
| Method | URL | Description |
| ------ | -------------------------------------------------------------------------------- | ------------------------------------------------------- |
| `GET` | `/api/v1/table/tables.json` | [Tables](#tables) |
| `GET` | `/api/v1/table/{database}/{scheme}/{table}.json` | [Table JSON](#table-json) |
| `GET` | `/api/v1/tiles/{database}/{scheme}/{table}/{z}/{x}/{y}.pbf` | [Tiles](#tiles) |
| `GET` | `/api/v1/tiles/{database}/{scheme}/{table}.json` | [Table TileJSON](#table-tile-json) |
| `DELETE` | `/api/v1/tiles/cache` | [Delete Cache](#cache-delete) |
| `GET` | `/api/v1/tiles/cache_size` | [Cache Size](#cache-size) |
| `GET` | `/viewer/{database}/{scheme}/{table}` | [Viewer](#viewer) |
| `GET` | `/api/v1/health_check` | Server health check: returns `200 OK` |## Using with Mapbox GL JS
[Mapbox GL JS](https://github.com/mapbox/mapbox-gl-js) is a JavaScript library for interactive, customizable vector maps on the web. It takes map styles that conform to the
[Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-js/style-spec), applies them to vector tiles that
conform to the [Mapbox Vector Tile Specification](https://github.com/mapbox/vector-tile-spec), and renders them using
WebGL.You can add a layer to the map and specify TileJSON endpoint as a vector source URL. You should also specify a `source-layer` property. For [Table JSON](#table-json) it is `{schema_name}.{table_name}` by default.
```js
map.addSource('points', {
type: 'vector',
url: `http://localhost:8000/api/v1/tiles/data/public/state_centroids/{z}/{x}/{y}.pbf`
});map.addLayer({
'id': 'state_centroids',
'type': 'circle',
'source': 'state_centroids',
'source-layer': 'public.state_centroids',
'paint': {
'circle-color': 'red'
}
});
```## Using with MapLibre
[MapLibre](https://maplibre.org/projects/maplibre-gl-js/) is an Open-source JavaScript library for publishing maps on your websites.```js
map.addSource('state_centroids', {
type: 'vector',
url: `http://localhost:8000/api/v1/tiles/data/public/state_centroids/{z}/{x}/{y}.pbf`
});map.addLayer({
'id': 'points',
'type': 'circle',
'source': 'state_centroids',
'source-layer': 'public.state_centroids',
'paint': {
'circle-color': 'red'
}
});
```## Using with Leaflet
[Leaflet](https://github.com/Leaflet/Leaflet) is the leading open-source JavaScript library for mobile-friendly interactive maps.
You can add vector tiles using [Leaflet.VectorGrid](https://github.com/Leaflet/Leaflet.VectorGrid) plugin. You must initialize a [VectorGrid.Protobuf](https://leaflet.github.io/Leaflet.VectorGrid/vectorgrid-api-docs.html#vectorgrid-protobuf) with a URL template, just like in L.TileLayers. The difference is that you should define the styling for all the features.
```js
L.vectorGrid
.protobuf('http://localhost:8000/api/v1/tiles/data/public/state_centroids/{z}/{x}/{y}.pbf', {
vectorTileLayerStyles: {
'public.state_centroids': {
color: 'red',
fill: true
}
}
})
.addTo(map);
```## Tables
Tables endpoint provides a listing of all the tables available to query as vector tiles.Tables endpoint is available at `/api/v1/table/tables.json`
```shell
curl http://localhost:8000/api/v1/table/tables.json
```Example Response
```json
[
{
"name": "states",
"schema": "public",
"type": "table",
"id": "public.states",
"database": "data",
"detailurl": "http://127.0.0.1:8000/api/v1/table/data/public/states.json",
"viewerurl": "http://127.0.0.1:8000/viewer/data/public/states"
},
{},...
```## Table JSON
Table endpoint is available at `/api/v1/table/{database}/{scheme}/{table}.json`
For example, `states` table in `public` schema in `data` database will be available at `/api/v1/table/data/public/states.json`
```shell
curl http://localhost:8000/api/v1/table/data/public/states.json
```Example Response
```json
{
"id": "public.states",
"schema": "public",
"tileurl": "http://127.0.0.1:8000/api/v1/tiles/data/public/states/{z}/{x}/{y}.pbf",
"viewerurl": "http://127.0.0.1:8000/viewer/data/public/states",
"properties": [
{
"name": "gid",
"type": "integer",
"description": null
},
{
"name": "geom",
"type": "geometry",
"description": null
},
{
"name": "state_name",
"type": "character varying",
"description": null
},
{
"name": "state_fips",
"type": "character varying",
"description": null
},
{
"name": "state_abbr",
"type": "character varying",
"description": null
},
{
"name": "population",
"type": "integer",
"description": null
}
],
"geometrytype": "ST_MultiPolygon",
"type": "table",
"minzoom": 0,
"maxzoom": 22,
"bounds": [
-178.2175984,
18.9217863,
-66.9692709999999,
71.406235408712
],
"center": [
-112.96125695842262,
45.69082939790446
]
}
```## Tiles
Tiles endpoint is available at `/api/v1/tiles/{database}/{scheme}/{table}/{z}/{x}/{y}.pbf`
For example, `states` table in `public` schema in `data` database will be available at `/api/v1/table/data/public/states/{z}/{x}/{y}.pbf`
### Fields
If you have a table with a large amount of fields you can limit the amount of fields returned using the fields parameter.
#### Note
If you use the fields parameter the tile will not be cached on the server.
For example, if we only want the `state_fips` field.
`/api/v1/table/data/public/states/{z}/{x}/{y}.pbf?fields=state_fips`
### CQL Filtering
CQL filtering is enabled via [pygeofilter](https://pygeofilter.readthedocs.io/en/latest/index.html). This allows you to dynamically filter your tiles database size for larger tiles.
For example, filter the states layer to only show states with a population greater than 1,000,000.
`/api/v1/table/data/public/states/{z}/{x}/{y}.pbf?cql_filter=population>1000000`
[Geoserver](https://docs.geoserver.org/stable/en/user/tutorials/cql/cql_tutorial.html) has examples of using cql filters.
#### Spatial Filters
| Filters |
| --- |
| Intersects |
| Equals |
| Disjoint |
| Touches |
| Within |
| Overlaps |
| Crosses |
| Contains |#### Note
If you use the cql_filter parameter the tile will not be cached on the server.
## Table Tile JSON
Table [TileJSON](https://github.com/mapbox/tilejson-spec) endpoint is available at `/api/v1/tiles/{database}/{scheme}/{table}.json`
For example, `states` table in `public` schema in `data` database will be available at `/api/v1/tiles/data/public/states.json`
```shell
curl http://localhost:8000/api/v1/tiles/data/public/states.json
```Example Response
```json
{
"tilejson": "2.2.0",
"name": "public.states",
"version": "1.0.0",
"scheme": "xyz",
"tiles": [
"http://127.0.0.1:8000/api/v1/tiles/data/public/states/{z}/{x}/{y}.pbf"
],
"viewerurl": "http://127.0.0.1:8000/viewer/data/public/states",
"minzoom": 0,
"maxzoom": 22
}
```## Cache Delete
The cache delete endpoint allows you to delete any vector tile cache on the server.This is a DELETE HTTP method endpoint.
In your request you have to pass the following.
```json
{
"database": "data",
"scheme": "public",
"table": "states"
}
```## Cache Size
Cache Size endpoint allows you to determine the size of a vector tile cache for each table.```shell
curl http://localhost:8000/api/v1/api/v1/tiles/cache_size
```Example Response
```json
[
{
"table": "data_public_counties",
"size_in_gigabytes": 0.004711238
},
{
"table": "data_public_states",
"size_in_gigabytes": 0.000034666
}
]
```## Viewer
The viewer allows to preview a tile dataset in a web map viewer.For example, you can view the states table at `/viewer/data/public/states`. It will automatically zoom to the extent of the table.
![Viewer Image](/images/viewer_demo.png "Viewer Image")