Construct and use map tile grids in different projection.

Overview

Morecantile

    +-------------+-------------+  ymax
    |             |             |
    |    x: 0     |    x: 1     |
    |    y: 0     |    y: 0     |
    |    z: 1     |    z: 1     |
    |             |             |
    +-------------+-------------+
    |             |             |
    |    x: 0     |    x: 1     |
    |    y: 1     |    y: 1     |
    |    z: 1     |    z: 1     |
    |             |             |
    +-------------+-------------+  ymin

xmin                            xmax

Construct and use map tile grids (a.k.a TileMatrixSet / TMS).

Test Coverage Package version Downloads License


Documentation: https://developmentseed.org/morecantile/

Source Code: https://github.com/developmentseed/morecantile


Morecantile is like mercantile (the best tool to work with Web Mercator tile indexes), but with support for other TileMatrixSet grids.

Morecantile follows the OGC Two Dimensional Tile Matrix Set specification found in http://docs.opengeospatial.org/is/17-083r2/17-083r2.html

Note: Variable matrix width tile set are not supported.

Install

$ pip install -U pip
$ pip install morecantile

# Or install from source:

$ pip install git+https://github.com/developmentseed/morecantile.git

Defaults Grids

  • CanadianNAD83_LCC: Lambert conformal conic NAD83 for Canada - EPSG:3978
  • EuropeanETRS89_LAEAQuad: ETRS89-extended / LAEA Europe - EPGS:3035
  • LINZAntarticaMapTilegrid: LINZ Antarctic Map Tile Grid (Ross Sea Region) - EPSG:5482
  • NZTM2000: LINZ NZTM2000 Map Tile Grid - EPSG:2193
  • UPSAntarcticWGS84Quad: Universal Polar Stereographic WGS 84 Quad for Antarctic - EPSG:5042
  • UPSArcticWGS84Quad: Universal Polar Stereographic WGS 84 Quad for Arctic - EPSG:5041
  • UTM31WGS84Quad: Example of UTM grid - EPSG:32631
  • WebMercatorQuad: Spherical Mercator - EPGS:3857 (default grid for Web Mercator based maps)
  • WorldCRS84Quad: CRS84 for the World - EPGS:4326 (WGS84)
  • WorldMercatorWGS84Quad: Elliptical Mercator projection - EPGS:3395

ref: http://schemas.opengis.net/tms/1.0/json/examples/

Implementations

  • rio-tiler: Create tile from raster using Morecantile TMS.
  • timvt: A lightweight PostGIS based dynamic vector tile server.

Changes

See CHANGES.md.

Contribution & Development

See CONTRIBUTING.md

License

See LICENSE

Authors

Created by Development Seed

Comments
  • Werid bounding boxes in NZTM

    Werid bounding boxes in NZTM

    When using NZTM TileMatrixSet the numbers appear to be off.

    import morecantile
    
    nztm = morecantile.tms.get('NZTM2000')
    print(nztm.xy_bounds(morecantile.Tile(1, 2, 0)))
    

    returns

    CoordsBbox(xmin=12293760.0, ymin=-7881280.0, xmax=14587520.0, ymax=-5587520.0)
    

    When viewing this tile inside of QGIS the top left point is { x: 1293760, y: 5412480 }

    I believe this is caused by https://github.com/developmentseed/morecantile/blob/master/morecantile/models.py#L305 as NZTM is defined as [y, x] rather than [x, y]

    opened by blacha 13
  • Pip install error

    Pip install error

    Hello, since the version bump to 3.1.0 we are getting the following output from pip. It seems like there's an issue with the package? Everything was fine under 3.0.5. Thanks for your help.

    #!/bin/bash -eo pipefail
    sudo pip3 install cogeo-mosaic
    Collecting cogeo-mosaic
      Downloading cogeo-mosaic-4.0.0.tar.gz (23 kB)
      Preparing metadata (setup.py) ... - done
    Collecting attrs
      Downloading attrs-21.4.0-py2.py3-none-any.whl (60 kB)
         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 60.6/60.6 KB 32.0 MB/s eta 0:00:00
    
    Collecting cachetools
      Downloading cachetools-5.0.0-py3-none-any.whl (9.1 kB)
    Collecting httpx
      Downloading httpx-0.22.0-py3-none-any.whl (84 kB)
         ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 84.2/84.2 KB 39.5 MB/s eta 0:00:00
    
    Collecting mercantile
      Downloading mercantile-1.2.1-py3-none-any.whl (14 kB)
    Collecting morecantile<4.0,>=3.0
      Downloading morecantile-3.1.0.tar.gz (25 kB)
      Preparing metadata (setup.py) ... - error
      error: subprocess-exited-with-error
      
      × python setup.py egg_info did not run successfully.
      │ exit code: 1
      ╰─> [36 lines of output]
          Traceback (most recent call last):
            File "<string>", line 36, in <module>
            File "<pip-setuptools-caller>", line 34, in <module>
            File "/tmp/pip-install-e4svnxu4/morecantile_2e4a53c9883345079bf39a2a4ca2e893/setup.py", line 45, in <module>
              "morecantile=morecantile.scripts.cli:cli",
            File "/usr/lib/python3/dist-packages/setuptools/__init__.py", line 145, in setup
              return distutils.core.setup(**attrs)
            File "/usr/lib/python3.7/distutils/core.py", line 121, in setup
              dist.parse_config_files()
            File "/usr/lib/python3/dist-packages/setuptools/dist.py", line 705, in parse_config_files
              ignore_option_errors=ignore_option_errors)
            File "/usr/lib/python3/dist-packages/setuptools/config.py", line 120, in parse_configuration
              meta.parse()
            File "/usr/lib/python3/dist-packages/setuptools/config.py", line 425, in parse
              section_parser_method(section_options)
            File "/usr/lib/python3/dist-packages/setuptools/config.py", line 398, in parse_section
              self[name] = value
            File "/usr/lib/python3/dist-packages/setuptools/config.py", line 183, in __setitem__
              value = parser(value)
            File "/usr/lib/python3/dist-packages/setuptools/config.py", line 513, in _parse_version
              version = self._parse_attr(value, self.package_dir)
            File "/usr/lib/python3/dist-packages/setuptools/config.py", line 348, in _parse_attr
              module = import_module(module_name)
            File "/usr/lib/python3.7/importlib/__init__.py", line 127, in import_module
              return _bootstrap._gcd_import(name[level:], package, level)
            File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
            File "<frozen importlib._bootstrap>", line 983, in _find_and_load
            File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
            File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
            File "<frozen importlib._bootstrap_external>", line 728, in exec_module
            File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
            File "/tmp/pip-install-e4svnxu4/morecantile_2e4a53c9883345079bf39a2a4ca2e893/morecantile/__init__.py", line 14, in <module>
              from .defaults import tms  # noqa
            File "/tmp/pip-install-e4svnxu4/morecantile_2e4a53c9883345079bf39a2a4ca2e893/morecantile/defaults.py", line 8, in <module>
              import attr
          ModuleNotFoundError: No module named 'attr'
          [end of output]
      
      note: This error originates from a subprocess, and is likely not a problem with pip.
    error: metadata-generation-failed
    
    × Encountered error while generating package metadata.
    ╰─> See above for output.
    
    note: This is an issue with the package mentioned above, not pip.
    hint: See above for details.
    
    
    Exited with code exit status 1
    
    opened by hackartisan 11
  • Quadkey support

    Quadkey support

    Tile matrix sets have the notion of X/Y/Z coordinates so technically we can generate a quadkey. However not all tile matrix sets have 4 children per parent which breaks the parent/child hierarchy. A good example of this is Canadian NAD83 LCC.

    This all being said, I do think there are many benefits to supporting quadkeys:

    • serialization/deserialization of tiles
    • server side caching (generating unique per-tile cache keys)
    • fast parent/child lookups

    I think this comes down to whether or not morecantile will support tile matrices which don't decimate by a factor of 4 (width or height is 2**zoom). From the README, docstrings, and general usage my thought is that it shouldn't, but that isn't entirely clear.

    opened by geospatial-jeff 7
  • Switch to pyproj for new morecantile major release

    Switch to pyproj for new morecantile major release

    in #58 we are proposing a major change to this library.

    When we started the development of morecantile we choose to use rasterio only to avoid adding requirements like pyproj (because morecantile was mostly made to work with rio-tiler). In addition for a long time rasterio wheels were stuck at proj 6 while pyproj were already using proj>=7, so we wanted to avoid using coordinates coming from 2 different proj version.

    Now that rasterio wheels uses proj>=7, if think we are in a better place to switch to pyproj and thus remove rasterio from this libraries.

    The main motivation is trying to avoid some weird behaviour with coordinate re-projection which seems to be better handled by proj (with rasterio, you use GDAL which use proj while with pyproj you directly use Proj).

    The PR is ready and the CI passes (still trying to match mercantile tests)

    What it means for libraries using morecantile

    Mostly nothing. The biggest breaking change is the type of CRS being returned by morecantile.TileMatrixSet.crs property, which is now of type pyproj.CRS instead of rasterio.crs.CRS. This is used in rio-tiler for example (https://github.com/cogeotiff/rio-tiler/search?l=Python&q=tms.crs). To help with the transition we are adding morecantile.TileMatrixSet.rasterio_crs property which will return a rasterio.crs.CRS. This method will only be available is rasterio is installed.

    import morecantile
    
    # before
    tms = morecantile.tms.get("WebMercatorQuad")
    crs = tms.crs
    
    # now 
    tms = morecantile.tms.get("WebMercatorQuad")
    crs = tms.rasterio_crs
    

    If no negative feedback, we'll do a pre-release next week

    help wanted 
    opened by vincentsarago 5
  • Non-Earth TMS definitions

    Non-Earth TMS definitions

    I'm trying to use this library to create TileMatrixSet definitions (ultimately for cogeo-mosaic, titiler and friends) for non-Earth (Mars) coordinate reference systems. Most aspects of the math are exactly the same, but recent Proj has gotten strict about ellipsoids. This is a good thing for most users, but the "Cannot find coordinate operations from 'EPSG:4326' to XXX" has become a source of dread for planetary scientists ;)

    I've been able to successfully adapt the TileMatrixSet definition to mostly work for the "Mars 2000" CRS, but I had to reimplement more than I ideally would to simply change the CRS:

    
    MARS2000_SPHERE = CRS.from_dict(
        {"proj": "longlat", "R": 3396190, "no_defs": True}
    )
    
    class MarsTMS(TileMatrixSet):
        _to_mars2000 = PrivateAttr()
        _from_mars2000 = PrivateAttr()
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
    
            # Mars 2000 sphere can be used because lat/lon are defined
            # as planetocentric on Mars
            self._to_mars2000 = Transformer.from_crs(
                self.supportedCRS, MARS2000_SPHERE, always_xy=True
            )
            self._from_mars2000 = Transformer.from_crs(
                MARS2000_SPHERE, self.supportedCRS, always_xy=True
            )
    
        @property
        def bbox(self):
            """Return TMS bounding box in WGS84."""
            bbox = self._to_mars2000.transform_bounds(*self.xy_bbox, densify_pts=21)
            return BoundingBox(*bbox)
    
        def xy(self, lng: float, lat: float, truncate=False) -> Coords:
            """Transform longitude and latitude coordinates to TMS CRS."""
            if truncate:
                lng, lat = truncate_lnglat(lng, lat)
    
            inside = point_in_bbox(Coords(lng, lat), self.bbox)
            if not inside:
                warnings.warn(
                    f"Point ({lng}, {lat}) is outside TMS bounds {list(self.bbox)}.",
                    PointOutsideTMSBounds,
                )
    
            x, y = self._from_mars2000.transform(lng, lat)
    
            return Coords(x, y)
    

    The lengthy redefinition is needed to replace the _to_wgs84 and _from_wgs84 definitions. Ideally, these could be replaced by _to_geographic and _from_geographic methods, with the geographic coordinate system being user-supplied (WGS84 by default). This could also help with other planets and other reasons people might define a custom ellipsoid.

    If you think I'm missing a simpler way to achieve this, please let me know. If not, I'm happy to supply a PR.

    opened by davenquinn 4
  • Official release of Morecantile 3.0 -> 23/09/2021

    Official release of Morecantile 3.0 -> 23/09/2021

    Dear All,

    I haven't heard any feedback since the release of the 3.0.0a0 release so I think we can go ahead and release 3.0.0 early next week.

    Regards,

    Vincent

    opened by vincentsarago 4
  • Custom CRS

    Custom CRS

    in #22 an user wanted to used a custom CRS defined from a proj4 string

    import morecantile 
    from rasterio.crs import CRS 
    
    crs = CRS.from_proj4("+proj=stere +lat_0=90 +lon_0=0 +k=2 +x_0=0 +y_0=0 +R=3396190 +units=m +no_defs") 
    extent = [-13584760.000,-13585240.000,13585240.000,13584760.000] 
    tms = morecantile.TileMatrixSet.custom(extent, crs, identifier="MarsNPolek2MOLA5k")  
    

    While the TMS creation works, the internal representation of the CRS won't work because morecantile is trying to create an URI type

    tms.supportedCRS                                                                                                                         
    >  'http://www.opengis.net/def/crs/EPSG/0/None'
    

    Because

    crs = CRS.from_proj4("+proj=stere +lat_0=90 +lon_0=0 +k=2 +x_0=0 +y_0=0 +R=3396190 +units=m +no_defs") 
    crs.to_epsg()
    > None
    

    I think we should default the tms.crs to the custom one instead of doing inputCRS -> toEPSG -> toURI -> toCRS

    cc @cirquelar

    opened by vincentsarago 4
  • Custom Tileset can't be set

    Custom Tileset can't be set

    I'm trying to create a custom tile matrix based on the example:

    import rasterio, morecantile from rasterio.crs import CRS crs = CRS.from_proj4("+proj=stere +lat_0=90 +lon_0=0 +k=2 +x_0=0 +y_0=0 +R=3396190 +units=m +no_defs") extent = [-13584760.000,-13585240.000,13585240.000,13584760.000] tms = morecantile.TileMatrixSet.custom(extent, crs, indentifier="MarsNPolek2MOLA5k") Traceback (most recent call last): File "", line 1, in TypeError: custom() got an unexpected keyword argument 'indentifier'

    if I remove 'indentifier':

    tms = morecantile.TileMatrixSet.custom(extent, crs, "MarsNPolek2MOLA5k") Traceback (most recent call last): File "", line 1, in File "/Users/fcalef/miniconda3/envs/py37/lib/python3.7/site-packages/morecantile/models.py", line 157, in custom width / (tile_width * matrix_scale[0]) / 2.0 ** zoom, TypeError: unsupported operand type(s) for /: 'float' and 'str'

    I don't see any obvious syntax mistakes.

    opened by cirquelar 4
  • adds ability to export non-EPSG CRSs URIs

    adds ability to export non-EPSG CRSs URIs

    grabs the authority, version and code from the CRS directly to encode the URIs. Related to #92 but can be merged separately. I'm not aware of any issues this would cause but I am open to hearing about them

    opened by AndrewAnnex 3
  • Units other than meters and degrees

    Units other than meters and degrees

    The referenced specification only considers Meters and Degrees. Would it be possible to consider other units? In the United States were have the State Plane Coordinate System with either defined units in "US Survey Foot" or "International Foot".

    US Survey Foot = 0.3048006096 International Foot = 0.3048

    I hard-coded the else statement to the US Survey Foot for EPSG:2276 data that I am working with just as a test. And I am very happy to have found success in properly tiling locally referenced imagery!

    I don't know Python, but I could take a crack at adding a case statement for the defined units if there is no objection.

    https://github.com/developmentseed/morecantile/blob/17020c555d4f09e3027cab755cf0f74744106774/morecantile/utils.py#L55

    From note g in http://docs.opengeospatial.org/is/17-083r2/17-083r2.html#table_2: If the CRS uses meters as units of measure for the horizontal dimensions, then metersPerUnit=1; if it has degrees, then metersPerUnit=2pa/360 (a is the Earth maximum radius of the ellipsoid).

    opened by lf73 3
  • [WIP] test equivalency against mercantile.tile

    [WIP] test equivalency against mercantile.tile

    The mercantile.tile and morecantile.tms.get("WebMercatorQuad").tile functions are returning slightly different values given the same lat/lon coordinate. This is because mercantile uses slightly more precision when defining the bounds of the Web Mercator tiling scheme. I updated the bounds of the TMS defined in morecantile/data to match the return of mercantile.xy_bounds(mercantile.Tile(0,0,0)). You'll notice that the first build fails, and tests are fixed when making this change.

    This change means our WebMercatorQuad deviates slightly from what is defined by OGC (https://docs.opengeospatial.org/is/17-083r2/17-083r2.html#62) but I think its worth it to align with mercantile.

    I also had to move the antimeredian test case into its own function, for some reason it fails when its included in the larger test case 🤷

    opened by geospatial-jeff 3
  • Feature idea - Tiled Mercator and Tiled Transverse Mercator (NGA-style)

    Feature idea - Tiled Mercator and Tiled Transverse Mercator (NGA-style)

    NGA has a "non-web-Mercator" tile grid document ("Map Projections for Tiled Raster Graphics, V1.0, 24 April 2015") available from https://nsgreg.nga.mil/doc/view?i=1810

    Its intended for GeoPackage (although application is a bit more general). Possibly useful to incorporate.

    opened by bradh 2
Replace MSFS2020's bing map to google map

English verison here 中文 免责声明 本教程提到的方法仅用于研究和学习用途。我不对使用、拓展该教程及方法所造成的任何法律责任和损失负责。 背景 微软模拟飞行2020的地景使用了Bing的卫星地图,然而卫星地图比较老旧,很多地区都是几年前的图设置直接是没有的。这种现象在全球不同地区

hesicong 272 Dec 24, 2022
A light-weight, versatile XYZ tile server, built with Flask and Rasterio :earth_africa:

Terracotta is a pure Python tile server that runs as a WSGI app on a dedicated webserver or as a serverless app on AWS Lambda. It is built on a modern

DHI GRAS 531 Dec 28, 2022
🌐 Local tile server for viewing geospatial raster files with ipyleaflet

?? Local Tile Server for Geospatial Rasters Need to visualize a rather large raster (gigabytes) you have locally? This is for you. A Flask application

Bane Sullivan 192 Jan 4, 2023
🌐 Local tile server for viewing geospatial raster files with ipyleaflet or folium

?? Local Tile Server for Geospatial Rasters Need to visualize a rather large (gigabytes) raster you have locally? This is for you. A Flask application

Bane Sullivan 192 Jan 4, 2023
A bot that tweets info and location map for new bicycle parking added to OpenStreetMap within a GeoJSON boundary.

Bike parking tweepy bot app A twitter bot app that searches for bicycle parking added to OpenStreetMap. Relies on AWS Lambda/S3, Python3, Tweepy, Flas

Angelo Trivisonno 1 Dec 19, 2021
This program analizes films database with adresses, and creates a folium map with closest films to the coordinates

Films-map-project UCU CS lab 1.2, 1st year This program analizes films database with adresses, and creates a folium map with closest films to the coor

Artem Moskovets 1 Feb 9, 2022
Python renderer for OpenStreetMap with custom icons intended to display as many map features as possible

Map Machine project consists of Python OpenStreetMap renderer: SVG map generation, SVG and PNG tile generation, Röntgen icon set: unique CC-BY 4.0 map

Sergey Vartanov 0 Dec 18, 2022
Python project to generate Kerala's distrcit level panchayath map.

Kerala-Panchayath-Maps Python project to generate Kerala's distrcit level panchayath map. As of now, geojson files of Kollam and Kozhikode are added t

Athul R T 2 Jan 10, 2022
A GUI widget for Linux to show current time in different timezones.

A GUI widget to show current time in different timezones (under development). To use this widget: Run scripts/startup.py Select a country. A list of t

B.Jothin kumar 11 Nov 10, 2022
A Django application that provides country choices for use with forms, flag icons static files, and a country field for models.

Django Countries A Django application that provides country choices for use with forms, flag icons static files, and a country field for models. Insta

Chris Beaven 1.2k Jan 3, 2023
GeoNode is an open source platform that facilitates the creation, sharing, and collaborative use of geospatial data.

Table of Contents What is GeoNode? Try out GeoNode Install Learn GeoNode Development Contributing Roadmap Showcase Most useful links Licensing What is

GeoNode Development Team 1.2k Dec 26, 2022
Use Mapbox GL JS to visualize data in a Python Jupyter notebook

Location Data Visualization library for Jupyter Notebooks Library documentation at https://mapbox-mapboxgl-jupyter.readthedocs-hosted.com/en/latest/.

Mapbox 620 Dec 15, 2022
How to use COG's (Cloud optimized GeoTIFFs) with Rasterio

How to use COG's (Cloud optimized GeoTIFFs) with Rasterio According to Cogeo.org: A Cloud Opdtimized GeoTIFF (COG) is a regular GeoTIFF file, aimed at

Marvin Gabler 8 Jul 29, 2022
A ready-to-use curated list of Spectral Indices for Remote Sensing applications.

A ready-to-use curated list of Spectral Indices for Remote Sensing applications. GitHub: https://github.com/davemlz/awesome-ee-spectral-indices Docume

David Montero Loaiza 488 Jan 3, 2023
Creates 3D geometries from 2D vector graphics, for use in geodynamic models

geomIO - creating 3D geometries from 2D input This is the Julia and Python version of geomIO, a free open source software to generate 3D volumes and s

null 3 Feb 1, 2022
OSMnx: Python for street networks. Retrieve, model, analyze, and visualize street networks and other spatial data from OpenStreetMap.

OSMnx OSMnx is a Python package that lets you download geospatial data from OpenStreetMap and model, project, visualize, and analyze real-world street

Geoff Boeing 4k Jan 8, 2023
Read and write rasters in parallel using Rasterio and Dask

dask-rasterio dask-rasterio provides some methods for reading and writing rasters in parallel using Rasterio and Dask arrays. Usage Read a multiband r

Dymaxion Labs 85 Aug 30, 2022
Location field and widget for Django. It supports Google Maps, OpenStreetMap and Mapbox

django-location-field Let users pick locations using a map widget and store its latitude and longitude. Stable version: django-location-field==2.1.0 D

Caio Ariede 481 Dec 29, 2022
Deal with Bing Maps Tiles and Pixels / WGS 84 coordinates conversions, and generate grid Shapefiles

PyBingTiles This is a small toolkit in order to deal with Bing Tiles, used i.e. by Facebook for their Data for Good datasets. Install Clone this repos

Shoichi 1 Dec 8, 2021