SVG generation using ST_AsSVG - Transform (EPSG: 4326) to (EPSG: 3857) - postgresql

I have a Django model which contains the coordinates for a polygon:
geometria = models.PolygonField(srid=4326, null=True, geography=True)
I manually took the lat-long coordinates for a polygon from the Google maps web interface and entered them into the database. I believe the gps coordinates Google maps provide are 4326.
I plotted these coordinates on google maps using #react-google-maps/api and it matches what I expected. (See below image)
Next I tried to replicate the polygon shape using Postgis, and create an SVG of it, but this is where I had problems. As you can see below the green polygon has the same basic shape, but has been stretched horizontally when compared to the output from google maps.
I believe the problem is that the svg is using the 4326 projection, instead of 3857 which is used by google maps? I have tried to transform the data in postgis, but nothing I do seems to make any difference. Note that when I create the svg without the ST_Transform, it is the same shape as below. Any ideas how I can solve this?
I am using the following SQL in Django to pull the data from the database:
cursor.execute("SELECT ST_AsSVG(ST_AsEWKT(ST_Transform(ST_AsEWKT(geometria),3857))) FROM public.locations_locationdata WHERE id= %s", [self.id])
Where geometria is the database field which contains the polygon.
I use the following python to build the svg file:
svg_string = []
svg_string.append('<svg viewBox="')
svg_string.append(calculated_view_box)
svg_string.append('" xmlns="http://www.w3.org/2000/svg" width="512" height="512" version="1.1" transform="scale(1 -1) rotate(90)" transform-origin="256 256">')
svg_string.append('<path fill="green" stroke="blue" stroke-width="1" d="')
svg_string.append(reconstruct_path_string)
svg_string.append('"/></svg>')
<svg viewBox="5735636.0 75092.0 419.0 619.0" xmlns="http://www.w3.org/2000/svg" width="512" height="512" version="1.1" transform="scale(1 -1) rotate(90)" transform-origin="256 256"><path fill="green" stroke="blue" stroke-width="1" d="M 5736044.89547394 75658.7303669334 L 5735771.38348506 75102.09404005 5735654.72065871 75164.2146256582 5735646.59433588 75700.4781146285 5735842.07136171 75663.4061145318 Z"/></svg>
Any ideas how I can fix the svg so that it matches the google maps shapes?

The problem was that I incorrectly transposed the lat and lng values when creating the GEOSGeometry object. I later fixed the transposition when passing the the lat and lng back to Google maps, which hid the problem.
See below:
#polygon = GEOSGeometry('POLYGON ((51.527768 -0.679638,51.525311 -0.674638,51.524263 -0.675196,51.524190 -0.680013,51.525946 -0.679680,51.527768 -0.679638))', srid=4326)
polygon = GEOSGeometry('POLYGON ((-0.679638 51.527768, -0.674638 51.525311, -0.675196 51.524263, -0.680013 51.524190, -0.679680 51.525946, -0.679638 51.527768))', srid=4326)
Coordinates should be (longitude latitude) pairs

Related

Google Earth Pro - create 3D plot from CSV with Longitude, Latitude and Altitude

I have two CSV's with longitude, latitude and altitude data and I want to plot both with different colors in Google Earth Pro (so 3D). Is this even possible? If so, how can I do this? I can only find 2D plotting.
Best
Do you want one set of placemarks to be in one color, and the other in another? In that case you should be able to select the placemarks imported from each CSV, and modify their styling or icon type following these instructions:
https://support.google.com/earth/answer/148142?hl=en#zippy=%2Cdrag-or-edit-the-placemark%2Cuse-a-custom-icon
If instead you're trying to set colors based on field values (e.g., altitude), you can create a style template as described her:
https://support.google.com/earth/answer/176685?hl=en#styletemplate&zippy=%2Cimport-generic-text-files%2Cmap-color-styles
HTH!

How to convert FeatureCollection to GeometryCollection or MultiPolygon?

I have many polygons that need to be drawn manually and then get geo-coordinates.
I need to get the coordinates of the drawn polygons in GeoJSON format.
In this format:
"{"type":"MultiPolygon","coordinates":[[[[37.4653933,55.3959159]...}"
"{"type":"Polygon","coordinates":[[[37.475738525390625,55.41420507450017]...}"
Or in this:
"{"type":"GeometryCollection","geometries":[{"type":"Polygon","coordinates":[[[-98.0419921875,39.027718840211605]...}]}"
I draw polygons at http://geojson.io/.
But from this site I can only get data in the format with the FeatureCollection type.
I found another site - https://rodic.fr/blog/online-conversion-between-geometric-formats/, on which I can convert to GeoJSON format, but this site can only convert type GeometryCollection.
I cannot find how to convert FeatureCollection to GeometryCollection or MultiPolygon or to Polygon.
How to solve?
Many thx!
To get the coordinates in the geojson format, you can use the following snippet:
WITH geojson_featurecollection AS (
SELECT ''::json AS fc
)
SELECT (json_array_elements(fc->'features'))->>'geometry'
FROM geojson_featurecollection;
in which you paste your entire FeatureCollection definition (coming from the http://geojson.io website after your edits) inside of the quotes

What projection is this geoTIF and how do I convert it?

I am working with viewing weather data online and the website I use (University of Oklahoma) provides a link to the data displayed as a geoTIF, for research purposes. This is a direct link to the geoTIF that I am requesting help with.
I am trying to use the image in a Mapbox map, but there seems to be an issue with projection. I use GDAL tools (though I am a novice) and I can't even figure out what projection it is in to start with. When I use gdalinfo, I get the following result :
Warning 1: RowsPerStrip not defined ... assuming all one strip.
Raster dataset parameters:
Projection:
RasterCount: 1
RasterSize (7000,3500)
Using driver GeoTIFF
Image Structure Metadata:
0: COMPRESSION=DEFLATE
1: INTERLEAVE=BAND
Corner Coordinates:
Upper Left (-130, 55)
Lower Left (-130, 20)
Upper Right (-60, 55)
Lower Right (-60, 20)
Center (-95, 37.5)
Coordinate System is:
Band 1 :
DataType: Float32
ColorInterpretation: Gray
Description:
Size (7000,3500)
BlockSize (7000,3500)
NoDataValue: -999
Offset: 0
Scale: 1
I have been converting other geoTIF files for Mapbox use with the following command successfully :
gdalwarp -t_srs EPSG:3857 example.tif example-projected.tif
... The above code always works except with the file I am needing help with. I am very new with GDAL and though I have been trying it is difficult for me. What am I not doing right and how would I do this the correct way?
Your geotiff has no embedded coordinate system associated although the corners are obviously geographic coordinates (unprojected). WGS84 is my guess.
My suggestion is defining a source coordinate system in your command [-s_srs srs_def] and see the result,
-s_srs EPSG:4326
If that doesn't work you'd better ask OU. They should know better.

Incorrect coordinates in mbtiles generated with Tippecanoe

I generated an mbtiles file using Tippecanoe with just -zg and --drop-densest-as-needed as extra parameters. I uploaded the file to Mapbox Studio and everything works well, both in Studio and when loading the tiles through a mobile app.
I then tried my luck at self-hosting the tiles, using a very basic HTTP server in Go. Tiles were transferred from SQLite to a PostgreSQL database (the reason for this is Go + PSQL is the existing stack for the app).
For some reason the features are shifted depending on the zoom level. At level 1, data that's supposed to be in the US is in the Antarctic, at zoom level 2 it's off the coast of Chile, etc. The only one properly working is level 0 as there's only one tile.
I checked what tiles Mapbox was requesting when in San Francisco for zoom level 11: column 327, row 791. No tile exists for this row/col combination in the .mbtiles file although there's data there.
Is there additional things to be done to the mbtiles besides looking them up in the database using the z/x/y? Or maybe stuff to configure on the app side?
Server code:
row := db.QueryRow(`
SELECT tile_data FROM tiles
WHERE
zoom_level = $1
AND tile_column = $2
AND tile_row = $3
`,
z, x, y,
)
On Android:
map.addSource(
VectorSource(
"tiles",
TileSet("2.2.0", "http://my.local.server:4000/tiles/{z}/{x}/{y}.mvt?key=2448A697EACDDC41432AAD9A1833E")
)
)
I tried setting the VectorSource's center and bounds found in the mbtiles metadata but it didn't change anything.
So I looked into existing server implementations and it turns out the offset is because the mbtiles are stored in a TMS format in which the Y coordinate is flipped. So we just need to convert the Y from the XYZ format to get the proper tile:
From Mapbox's own Node implementation:
// Flip Y coordinate because MBTiles files are TMS.
y = (1 << z) - 1 - y;
1 << z is the number of rows for a given zoom level, or two to the power of z.
More info about XYZ vs TMS can also be found here.

Put points on the map, longitude/latitude not where they should be although SRID the same

Thank you for looking at this - I'm sure it's a simple question but this is all very new to me and after a lot of internet searching my points are still in the sea!
I have a set of UK postcode data that I have converted into latitude and longitude. I also have a UK counties shape file.
The code that I have used to convert the latitude/longitude to a geometry point column is as follows:
ALTER TABLE colic ADD COLUMN longlat geometry(POINT,27700);
update colic set longlat = st_setsrid(st_point( longitude, latitude), 27700);
And this produces a column that has values as follows (I've only included a couple!):
"0101000020346C000048BF7D1D3867E83FC05B2041F1334A40"
"0101000020346C0000F085C954C1A8F7BFA1F831E6AE954A40"
"0101000020346C000020D26F5F07CEF4BFE3361AC05B504A40"
"0101000020346C00007D3F355EBA49F73FB6847CD0B3614A40"
The .prj from my shape file is:
PROJCS["British_National_Grid", GEOGCS["GCS_OSGB_1936",
DATUM["D_OSGB_1936", SPHEROID["Airy_1830",6377563.396,299.3249646]],
PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],
PROJECTION["Transverse_Mercator"],
PARAMETER["False_Easting",400000.0],
PARAMETER["False_Northing",-100000.0],
PARAMETER["Central_Meridian",-2.0],
PARAMETER["Scale_Factor",0.9996012717],
PARAMETER["Latitude_Of_Origin",49.0], UNIT["Meter",1.0]]
And I set its SRID to 27700 when I upload it using the PostGIS shapefile uploader.
In PG Admin, when I ask:
select st_srid(geom) from counties limit 1;
select st_srid(longlat) from colic limit 1;
I get 27700 for both.
But...when I try any spatial query I get no response, and when I load the layers into quantum, the point data are off the tip of Cornwall in the north Atlantic, and only represented as one dot on the scale of the counties map.If I zoom in on them, they are 'there', but just not in east anglia where they should be!
This is my first attempt at both SQL and mapping - I'm sure there is something really simple that I have missed.
You are mixing up spatial references (SRS). The SRS in the .prj file (aka SRID=27700) is projected eastings and northings, which have units of metres. This is not latitude and longitude! Furthermore, it is a deception to call a column longlat when it isn't for longitude/latitude coordinates.
If you try to insert latitude/longitude in a column with SRID=27700, the points will not behave as expected, e.g., they will be in the far bottom left corner of a map.
If you have lat/long data from WGS84 (SRID=4326), you can transform this to eastings and northings:
UPDATE colic SET
geom = ST_Transform(ST_SetSRID(ST_Point(longitude, latitude), 4326), 27700);