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)?



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.


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)

| improve this answer | |

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$
    start_index integer;
    end_index integer;
    srid integer;
    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)
        points[i] = ST_Transform(points[i], srid);

    RETURN ST_GeomFromEWKT(replace(ST_AsEWKT(ST_MakeLine(points)), 'LINESTRING', 'CIRCULARSTRING'));
| improve this answer | |

Try ST_LineToCurve


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)')])))


"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)')])))


"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?

| improve this answer | |
  • 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. – EM0 Nov 10 '11 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. – CaptDragon Nov 10 '11 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. – CaptDragon Nov 10 '11 at 15:23
  • You're right, I should have put in an example. Edited the question to include it. – EM0 Nov 10 '11 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. – CaptDragon Nov 11 '11 at 14:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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