[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