GeoDjango: strip z dimension; force 2D

761 views
Skip to first unread message

Jônatas Castro

unread,
Mar 7, 2016, 1:43:05 PM3/7/16
to Django users
In my project I need to import shapefiles and same some geometry.

Some of these are MULTIPOLYGON Z type, but all Z coordinates are 0-value.

When I try to save the geometry, I get the error: "Geometry has Z dimension but column does not".

What is the best way to strip the Z dimension?



My code:


ds = DataSource(file_path, encoding='ISO-8859-1')
layers = ds[0]

#need something HERE to coerce geometry to 2D

obj=MyModel(geometry=GEOSGeometry(layers[0].geom.hex))
obj.save()

Alex Mandel

unread,
Mar 7, 2016, 1:52:39 PM3/7/16
to django...@googlegroups.com, geod...@googlegroups.com
1. There a GeoDjango sublist, better place to ask.
2. Strip out the Z when doing the database import, you don't say which
db backend your're using.
2a. If you can't do it on import than do it with an update query.

http://gis.stackexchange.com/questions/78142/how-can-i-strip-out-z-values-in-postgis

Thanks,
Alex

On 03/07/2016 10:36 AM, Jônatas Castro wrote:
> In my project I need to import *shapefiles* and same some geometry.
>
> Some of these are *MULTIPOLYGON Z* type, but all Z coordinates are 0-value.
>
> When I try to save the geometry, I get the error: *"Geometry has Z
> dimension but column does not".*
>
> *What is the best way to strip the Z dimension?*
>
>
>
> My code:
>
>
>
> *ds = DataSource(file_path, encoding='ISO-8859-1')layers = ds[0]*
>
> *#need something HERE to coerce geometry to 2D*
>
>
> *obj=MyModel(geometry=GEOSGeometry(layers[0].geom.hex))*
> *obj.save()*
>

Jason

unread,
Mar 8, 2016, 11:34:35 AM3/8/16
to Django users, geod...@googlegroups.com, te...@wildintellect.com
I had a similar issue when uploading a kml to geojson conversion to postgis using geodjango.  There is no efficient way to do it in Django, so I ended up doing a workaround

  • Create two geometry types, one with dims=2 and other with dims=3.  Allow both to be null and set default to null
  • When updating, check the geometry dimension via GEOSGeometry.hasz.  If the return is 2, save the geom in the 2D field, otherwise save to the 3D
You can create a save/retrieve method on the model to handle this for you.

a.gr...@gmail.com

unread,
Dec 19, 2016, 7:17:09 AM12/19/16
to Django users, geod...@googlegroups.com, te...@wildintellect.com
Jason: when you say create 2 geometry types one with 2 dimensions etc... how do you specify how many dimensions to have?
Because I created the field in this way: 

geom = models.MultiPolygonField(geography=True, spatial_index=True)

and let the Django migration do the job, but I don't know how to specify that it's a 3D field.

Thanks

George Silva

unread,
Dec 19, 2016, 10:35:50 AM12/19/16
to django-users, geod...@googlegroups.com, te...@wildintellect.com
There is a way to coerce the input to 2d. It's not pretty, but it works.

from django.contrib.gis.geos.prototypes.io import wkt_w
wkt = wkt_w(dim=2).write(input_geom).decode()
geom = GEOSGeometry(wkt, srid=4674)

Imagine that you get input_geom from somewhere. In our case it was coming from a KML upload. We forced it to 2d using that snippet of code.


--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/073345f1-0a70-4645-9c87-577c89b9a511%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
George R. C. Silva
Sigma Geosistemas LTDA
----------------------------

a.gr...@gmail.com

unread,
Dec 19, 2016, 11:24:10 AM12/19/16
to Django users, geod...@googlegroups.com, te...@wildintellect.com
Hi,

not sure if I did the right thing or not, but I just altered the table in this way https://github.com/alphagov/land-availability-api/pull/20/files#diff-f8cf5fd1898b907b7e7cc07dcc455602R15
(yes, the code is opensource!) because I've also noticed that GeoDjango doesn't have an equivalent of MultiPolygonZ so it must be created with a SQL command.


On Monday, 19 December 2016 15:35:50 UTC, george wrote:
There is a way to coerce the input to 2d. It's not pretty, but it works.

from django.contrib.gis.geos.prototypes.io import wkt_w
wkt = wkt_w(dim=2).write(input_geom).decode()
geom = GEOSGeometry(wkt, srid=4674)

Imagine that you get input_geom from somewhere. In our case it was coming from a KML upload. We forced it to 2d using that snippet of code.

On Mon, Dec 19, 2016 at 9:51 AM, <a.gr...@gmail.com> wrote:
Jason: when you say create 2 geometry types one with 2 dimensions etc... how do you specify how many dimensions to have?
Because I created the field in this way: 

geom = models.MultiPolygonField(geography=True, spatial_index=True)

and let the Django migration do the job, but I don't know how to specify that it's a 3D field.

Thanks

On Tuesday, 8 March 2016 16:34:35 UTC, Jason wrote:
I had a similar issue when uploading a kml to geojson conversion to postgis using geodjango.  There is no efficient way to do it in Django, so I ended up doing a workaround

  • Create two geometry types, one with dims=2 and other with dims=3.  Allow both to be null and set default to null
  • When updating, check the geometry dimension via GEOSGeometry.hasz.  If the return is 2, save the geom in the 2D field, otherwise save to the 3D
You can create a save/retrieve method on the model to handle this for you.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.

To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.

Rukaya Johaadien

unread,
Aug 25, 2017, 5:32:04 AM8/25/17
to Django users
I did the following: 

from django.contrib.gis.geos import GEOSGeometry, WKTWriter
wkt_w = WKTWriter()
wkt_w.outdim = 2 # This sets the writer to output 2D WKT
polygon = GEOSGeometry(json.dumps(item['geometry'])) # The 3D geometry
temp = wkt_w.write(polygon)
polygon = GEOSGeometry(temp) # The 3D geometry

Reply all
Reply to author
Forward
0 new messages