3

I'm looking to ensure that all geometries saved to the database are three-dimensional. It's easy enough to do with a call to the database,

select ST_Force_3D( ST_GeomFromText( blah blah ) )

...but that means for every object saved in the database, we make two database calls. Yuck!

Is there a simple way of invoking PostGIS functions without making a call to the database? We're using PostGIS 1.5 on top of Postgres 9.1 with GeoDjango on top of Python 2.7.

I've been working with GEOSGeometry objects, and they will tell you if your geometry is three-dimensional with the .hasz function, but I'm looking to FORCE everything to be three-dimensional without having to manually add a third dimension for every coordinate pair on every geometry we create.

Thanks!

1
  • Also, if you attempt to invoke set_z(0) on the GEOSGeometry object, it will throw an error: GEOSException: Cannot set Z on 2D Point.
    – user8472
    Commented Jun 27, 2012 at 15:06

2 Answers 2

2

I think you'll just have to make sure the points are 3d on creation, whenever that may be. If you have the 2d points in a list it's easy to convert them.

points_2d = [Point(1,1), ...]

# create new points with z value
points_3d = [Point(pnt.x, pnt.y, 0) for pnt in points_2d]
2

You have two options inside of Postgis. Either use the ST_Force_3D function in your INSERT statement or create a trigger for that table.

I have not run these on an actual database, so there may be some syntax issues, but the general idea should be fine.

Insert statement:

INSERT INTO mytable (the_geom) VALUES(ST_Force_3D(ST_GeomFromText('POINT (0 0)'))
)

Or Trigger:

-- General method that can be reused for other tables
CREATE OR REPLACE FUNCTION Force3DOnChange()
  RETURNS trigger AS
$BODY$
DECLARE
BEGIN
    NEW.the_geom = ST_Force_3D(NEW.the_geom);

    RETURN NEW;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

-- Specific Trigger function, must be created once per table
CREATE TRIGGER Force3DOn_mytable
  BEFORE INSERT OR UPDATE
  ON mytable
  FOR EACH ROW
  EXECUTE PROCEDURE Force3DOnChange();

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.