5

I'd like to make a CIRCULARSTRING in PostGIS 2.0.0 out of points that are calculated as part of the query (rather than constants). For a LINESTRING I can do this using ST_MakeLine(). Is there an equivalent for CIRCULARSTRING or some other way to do this?

I have 3 points that are calculated in some way (in the example let's just use ST_GeomFromText):

SELECT ST_GeomFromText('POINT(10 10)'), ST_GeomFromText('POINT(15 10)'), ST_GeomFromText('POINT(10 20)') 

What I want to get is CIRCULARSTRING(10 10, 15 10, 10 20).

If I run:

ST_LineToCurve(ST_MakeLine(ARRAY[ST_GeomFromText('POINT(10 10)'), ST_GeomFromText('POINT(15 10)'), ST_GeomFromText('POINT(10 20)')])) 

That gives me LINESTRING(10 10,15 10,10 20), not a CIRCULARSTRING.

Same question for CURVEPOLYGON - what can I use instead of ST_MakePolygon (which returns "Shell is not a line" if I pass in a CIRCULARSTRING)?

3 Answers 3

6

EM,

What you are asking for is a good idea, and I think fairly trivial to implement. I would suggest posting a ticket enhancement on PostGIS bug tracking. Maybe call it ST_MakeCurveLine or something like taht.

http://trac.osgeo.org/postgis/newticket

It probably won't make it into 2.0 since we are nearing feature freeze, but you never know so probably only things people are willing to pay for will have a chance to be added. At anyrate if you put it in will most likely make it for 2.1.

As a quick fix, what you could do is use ST_MakeLine in combo with ST_AsText and ST_CurveToLine.

So something like ST_CurveToLine((replace(ST_AsText(ST_MakeLine(yourpointset)), 'LINESTRING', 'CIRCULARLINESTRING'))::geometry)

1
  • Thanks, I think the string replacement workaround should work. I've raised a ticket: trac.osgeo.org/postgis/ticket/1291 Commented Nov 14, 2011 at 0:31
2

This is the function I ended up writing, based on LR1234567's answer:

CREATE OR REPLACE FUNCTION make_circularstring(points geometry(Point)[]) RETURNS geometry(CircularString) AS $BODY$ DECLARE start_index integer; end_index integer; srid integer; BEGIN start_index = array_lower(points, 1); end_index = array_upper(points, 1); -- The start and end points must have the same SRID. Transforming them is not safe, because this function must -- return a CIRCULARSTRING with the start and end points exactly matching the input. srid = ST_SRID(points[start_index]); IF (ST_SRID(points[end_index]) != srid) THEN RAISE EXCEPTION 'Start point SRID (%) differs from end point SRID (%) - they must match.', ST_AsEWKT(points[start_index]), ST_AsEWKT(points[end_index]); END IF; -- ... but all the points in-between can be transformed. FOR i IN (start_index + 1) .. (end_index - 1) LOOP points[i] = ST_Transform(points[i], srid); END LOOP; RETURN ST_GeomFromEWKT(replace(ST_AsEWKT(ST_MakeLine(points)), 'LINESTRING', 'CIRCULARSTRING')); END $BODY$ LANGUAGE plpgsql STABLE; 
0

Try ST_LineToCurve

ST_LineToCurve — Converts a LINESTRING/POLYGON to a CIRCULARSTRING, CURVED POLYGON

I know it's not the equivalent to ST_MakeLine, but you can use ST_MakeLine then convert it to your CURVED POLYGON or CIRCULARSTRING using ST_LineToCurve.

You should be able to do something like:

select ST_LineToCurve(ST_MakeLine(...)) 

EDIT #1: Okay i do not fully understand why sometimes the ST_LineToCurve returns a Linestring but these are some behaviors i have noticed and maybe that's why they say it's not "fully supported".

A valid circular string must have an odd number of points greated than 1.

Also, It seems as if it doesn't follow a straight path, it will return a LINESTRING.

For example:

This Straight Line:

select ST_AsEWKT(ST_LineToCurve(ST_MakeLine(ARRAY[ST_GeomFromText('Point(10 15)'), ST_GeomFromText('POINT(20 30)'), ST_GeomFromText('POINT(30 45)'), ST_GeomFromText('POINT(40 60)')]))) 

returns:

"CIRCULARSTRING(10 15,30 45,40 60)"

This Non-Straight line:

select ST_AsEWKT(ST_LineToCurve(ST_MakeLine(ARRAY[ST_GeomFromText('Point(11 15)'), ST_GeomFromText('POINT(20 30)'), ST_GeomFromText('POINT(30 45)'), ST_GeomFromText('POINT(40 60)')]))) 

returns:

"LINESTRING(11 15,20 30,30 45,40 60)"

If it were me having this problem i would join the postgis-users and/or postgis-devel email lists and shoot of this behavior to them and see what they say. Is it by design? Is it because of a bug or the not fully supported issue?

7
  • Thanks, but that won't work in my case, because I don't have the line that's a close approximation of the curve. I only have the 3 points that CIRCULARSTRING takes. In fact, after I create a CIRCULARSTRING I'm going to convert it to a LINESTRING using ST_CurveToLine. Commented Nov 10, 2011 at 4:16
  • Sorry, now i'm confused. Your questions says you want to get a CIRCULARSTRING from points and now your saying you want to get a LINESTRING (a group of points) from CIRCULARSTRING using ST_CurveToLine. FYI: People are reluctant to answer questions that do not provide examples of inputs or desired outputs. Please provide an example of data you are working with and what you expect so your question becomes clear and people can test the data and answer your question with confidence. I'm just telling you because i know you're new here and i would like to see your questions answered. Commented Nov 10, 2011 at 15:21
  • @EM: Communication is flawed and riddled with misunderstandings. By providing examples you help eliminated those misunderstandings. Please edit your original question and provide examples. Commented Nov 10, 2011 at 15:23
  • You're right, I should have put in an example. Edited the question to include it. Commented Nov 10, 2011 at 23:42
  • Excellent! you're much more likely to get more responses now. I'll try myself as soon as i get some free time. Commented Nov 11, 2011 at 14:49

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.