[postgis-users] MakeLine(geometry, geometry) bug with 3d points

Graham Davis gdavis at refractions.net
Tue Aug 30 15:49:19 PDT 2005


Hi,

I've been trying to write a plpgsql trigger that automatically takes two 
3d points and creates a linestring from them.   Within the script, I 
have selected the 2 points to be stored in plpgsql variables using 
SELECT INTO statements.  The variables are declared as the same type as 
the point column (which stores 3d points).  When I insert the new 
linestring using MakeLine(geometry, geometry), if I have setup my 
geometry column as a 3d linestring, I get a check constraint 
"enforce_dims_geom" violation.  The following was used to create the 
geometry column:

SELECT AddGeometryColumn('asset_position_lines', 'geom', 4326, 
'LINESTRING', 3);

It seems the MakeLine() function makes the points into 2d, and the 
resulting linestring will not be a legal entry into the table.  So I 
tried changing the column to be 2d, and the script runs, but the 
function obviously still results in a linestring with only 2d points.  
Not only that, it takes the extra coordinate from the first point (z) 
and starts off the second point with that coordinate.

For example, if point1 is (20 40 5) and point2 is (30 50 5), and I call 
MakeLine(point1, point2), the resulting linestring will have the 
following two points A and B:  pointA is (20 40) and pointB is (5 30).

So I changed the geometry column back to 3d, and tried to force the 
points and resulting line into 3d using force_3d().  The result was that 
it did the same thing as listed above (it took only the x and y 
coordinates of the first point, then inserted 0 as the z coordinate, 
then took the remaining coordinates of the first point and started the 
second point with that).  So using the same points in the above example, 
the resulting line had two points A and B as follows: pointA (20 40 0) 
and pointB (5 30 0).

It seems like the MakeLine() function only works with 2d points.  Is 
this something that can be fixed to work with more dimensions?

For an easy way to illustrate how this does not work, simply type this 
query into your postgres:

SELECT AsEWKT(MakeLine(MAKEPOINT(20,40,5), MAKEPOINT(30,50,5)));

The result should be something like  LINESTRING(20 40 5,30 50 5) but it 
actually results in this:  LINESTRING(20 40,5 30)

As you can see, it only uses the x and y coordinates, and the z 
coordinate of the first point gets carried over into the next point.

A similar query when trying to force the points into 3d:

SELECT AsEWKT(force_3d(MakeLine(force_3d(MAKEPOINT(20,40,5)), 
force_3d(MAKEPOINT(30,50,5)))));

results in:  LINESTRING(20 40 0,5 30 0)

Currently I've coded a work around in my script which essentially uses 7 
functions instead of the one now, and it is much slower (almost 50% 
slower than using MakeLine) but it works.  It basically looks like this 
(I removed all the concatenation parts so it's easier to read for you): 
GeomFromEWKT('SRID=4326;LINESTRING( X(point1) Y(point1) Z(point1), 
X(point2) Y(point2) Z(point2) )');

Anyways, this work around is much too slow for what I am trying to do, 
and a MakeLine() that works with 3d points would be much better.  Is 
anyone able to help me with this problem?  Thanks!

-- 
Graham Davis
Refractions Research Inc.
gdavis at refractions.net




More information about the postgis-users mailing list