diff --git a/docs/cli.rst b/docs/cli.rst index 78c33b8ae..5ed7a4ef0 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -3014,6 +3014,28 @@ Eight (case-insensitive) types are allowed: .. note:: In Python: :ref:`table.add_geometry_column() ` CLI reference: :ref:`sqlite-utils add-geometry-column ` +.. _cli_spatialite_populate_points: + +Populating points from latitude and longitude +--------------------------------------------- + +For an existing ``locations`` table with numeric ``longitude`` and ``latitude`` columns in WGS84 degrees, add a point column and populate it with ``MakePoint``: + +.. code-block:: bash + + sqlite-utils add-geometry-column locations.db locations geometry --type POINT --srid 4326 + sqlite-utils locations.db 'update locations set geometry = MakePoint(longitude, latitude, 4326)' --load-extension=spatialite + +Add the geometry column only once. Run the ``UPDATE`` again to refresh it after coordinates change or new rows are inserted. ``MakePoint`` takes longitude first, and the SRID must match the column. It does not reproject coordinates. + +Load SpatiaLite for each query that uses its functions, for example to check the stored points: + +.. code-block:: bash + + sqlite-utils locations.db 'select AsText(geometry) as point, SRID(geometry) as srid from locations' --load-extension=spatialite + +See :ref:`python_api_gis_populate_points` for a complete Python example and handling of missing coordinates. + .. _cli_spatialite_indexes: Adding spatial indexes diff --git a/docs/python-api.rst b/docs/python-api.rst index d515642a5..0740db895 100644 --- a/docs/python-api.rst +++ b/docs/python-api.rst @@ -3515,6 +3515,50 @@ Adding geometry columns .. note:: In the CLI: :ref:`sqlite-utils add-geometry-column ` +.. _python_api_gis_populate_points: + +Populating points from latitude and longitude +--------------------------------------------- + +Adding a geometry column does not populate it from existing coordinate columns. Use SpatiaLite's ``MakePoint(longitude, latitude, srid)`` function to fill it. For example, starting with a new ``locations.db`` file: + +.. code-block:: python + + from sqlite_utils import Database + + with Database("locations.db") as db: + db.init_spatialite() + locations = db.table("locations") + locations.insert_all([ + {"id": 1, "name": "London", "latitude": 51.509865, "longitude": -0.118092}, + {"id": 2, "name": "Paris", "latitude": 48.8566, "longitude": 2.3522}, + ], pk="id") + locations.add_geometry_column("geometry", "POINT", srid=4326) + db.execute(""" + update locations + set geometry = MakePoint(longitude, latitude, 4326) + """) + print(list(db.query(""" + select name, AsText(geometry) as point, SRID(geometry) as srid + from locations order by id + """))) + +This prints: + +.. code-block:: python + + [{'name': 'London', 'point': 'POINT(-0.118092 51.509865)', 'srid': 4326}, + {'name': 'Paris', 'point': 'POINT(2.3522 48.8566)', 'srid': 4326}] + +``MakePoint`` takes **longitude first**, then latitude. The example assumes the coordinates are already in WGS84 longitude/latitude degrees (SRID 4326). The SRID must match the geometry column; specifying it labels the coordinates and does not transform them from another coordinate system. + +The ``UPDATE`` fills or replaces the geometry for every row. It is a one-time conversion, not an automatic link between the columns: run it again after changing coordinates or inserting more rows. Missing coordinates produce a ``NULL`` geometry in this nullable column. Validate coordinate values before converting them. + +For an existing database, load the extension on each new connection with ``db.init_spatialite()``. Add the geometry column only once. You can then run the ``UPDATE`` and query above, and optionally :ref:`create a spatial index `. For inserting geometry from a single WKT value, see :ref:`python_api_conversions`. + +.. note:: + In the CLI: :ref:`cli_spatialite_populate_points` + .. _python_api_gis_create_spatial_index: Creating a spatial index