[SCM] PostGIS branch master updated. 3.6.0rc2-137-g976adccb9
git at osgeo.org
git at osgeo.org
Wed Oct 15 10:01:14 PDT 2025
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "PostGIS".
The branch, master has been updated
via 976adccb9b11f9f47da2aafe0e524d3207c08914 (commit)
via dba29bac7b4d2a58730953dad939e5dafd28b78b (commit)
from c33c1a582e5b468bd54e249b2f54d9ade37bd9e8 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 976adccb9b11f9f47da2aafe0e524d3207c08914
Merge: c33c1a582 dba29bac7
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date: Wed Oct 15 10:01:06 2025 -0700
Merge branch 'master-5754'
commit dba29bac7b4d2a58730953dad939e5dafd28b78b
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date: Wed Oct 15 09:14:37 2025 -0700
ST_ForcePolygonCCW unexpectedly reverses non-polygonal geometries too, references #5754
diff --git a/liblwgeom/cunit/cu_gserialized1.c b/liblwgeom/cunit/cu_gserialized1.c
index 47fb42e02..f0c3dc1b1 100644
--- a/liblwgeom/cunit/cu_gserialized1.c
+++ b/liblwgeom/cunit/cu_gserialized1.c
@@ -751,8 +751,9 @@ static void test_lwgeom_force_clockwise(void)
/* counterclockwise, must be reversed */
geom = lwgeom_from_wkt("POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))", LW_PARSER_CHECK_NONE);
- CU_ASSERT_FALSE(lwgeom_is_clockwise(geom));
+ CU_ASSERT(lwgeom_has_orientation(geom,LW_COUNTERCLOCKWISE));
lwgeom_force_clockwise(geom);
+ CU_ASSERT(lwgeom_has_orientation(geom,LW_CLOCKWISE));
in_ewkt = "POLYGON((0 0,0 10,10 10,10 0,0 0))";
out_ewkt = lwgeom_to_ewkt(geom);
if (strcmp(in_ewkt, out_ewkt))
@@ -763,8 +764,9 @@ static void test_lwgeom_force_clockwise(void)
/* clockwise, fine as is */
geom = lwgeom_from_wkt("POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))", LW_PARSER_CHECK_NONE);
- CU_ASSERT_TRUE(lwgeom_is_clockwise(geom));
+ CU_ASSERT(lwgeom_has_orientation(geom,LW_CLOCKWISE));
lwgeom_force_clockwise(geom);
+ CU_ASSERT(lwgeom_has_orientation(geom,LW_CLOCKWISE));
in_ewkt = "POLYGON((0 0,0 10,10 10,10 0,0 0))";
out_ewkt = lwgeom_to_ewkt(geom);
if (strcmp(in_ewkt, out_ewkt))
@@ -775,8 +777,8 @@ static void test_lwgeom_force_clockwise(void)
/* counterclockwise shell (must be reversed), mixed-wise holes */
geom = lwgeom_from_wkt("POLYGON((0 0,10 0,10 10,0 10,0 0),(2 2,2 4,4 2,2 2),(6 2,8 2,8 4,6 2))", LW_PARSER_CHECK_NONE);
- CU_ASSERT_FALSE(lwgeom_is_clockwise(geom));
lwgeom_force_clockwise(geom);
+ CU_ASSERT(lwgeom_has_orientation(geom,LW_CLOCKWISE));
in_ewkt = "POLYGON((0 0,0 10,10 10,10 0,0 0),(2 2,4 2,2 4,2 2),(6 2,8 2,8 4,6 2))";
out_ewkt = lwgeom_to_ewkt(geom);
if (strcmp(in_ewkt, out_ewkt))
@@ -785,10 +787,11 @@ static void test_lwgeom_force_clockwise(void)
lwfree(out_ewkt);
lwgeom_free(geom);
- /* clockwise shell (fine), mixed-wise holes */
+ /* clockwise shell (fine), mixed-wise holes, so not oriented */
geom = lwgeom_from_wkt("POLYGON((0 0,0 10,10 10,10 0,0 0),(2 2,4 2,2 4,2 2),(6 2,8 4,8 2,6 2))", LW_PARSER_CHECK_NONE);
- CU_ASSERT_FALSE(lwgeom_is_clockwise(geom));
+ /* fix it and then it is oriented */
lwgeom_force_clockwise(geom);
+ CU_ASSERT(lwgeom_has_orientation(geom,LW_CLOCKWISE));
in_ewkt = "POLYGON((0 0,0 10,10 10,10 0,0 0),(2 2,4 2,2 4,2 2),(6 2,8 2,8 4,6 2))";
out_ewkt = lwgeom_to_ewkt(geom);
if (strcmp(in_ewkt, out_ewkt))
@@ -803,10 +806,11 @@ static void test_lwgeom_force_clockwise(void)
geom = lwgeom_from_hexwkb(in_ewkt, LW_PARSER_CHECK_NONE);
geom2 = lwgeom_from_hexwkb(in_ewkt, LW_PARSER_CHECK_NONE);
lwgeom_force_clockwise(geom2);
+ CU_ASSERT(lwgeom_has_orientation(geom,LW_CLOCKWISE));
/** use same check instead of strcmp to account
for difference in endianness **/
- CU_ASSERT( lwgeom_same(geom, geom2) );
+ CU_ASSERT(lwgeom_same(geom, geom2));
lwgeom_free(geom);
lwgeom_free(geom2);
}
diff --git a/liblwgeom/liblwgeom.h.in b/liblwgeom/liblwgeom.h.in
index 54eb1e7ed..752569540 100644
--- a/liblwgeom/liblwgeom.h.in
+++ b/liblwgeom/liblwgeom.h.in
@@ -1379,10 +1379,12 @@ extern int lwgeom_startpoint(const LWGEOM* lwgeom, POINT4D* pt);
extern void interpolate_point4d(const POINT4D *A, const POINT4D *B, POINT4D *I, double F);
/**
-* Ensure the outer ring is clockwise oriented and all inner rings
-* are counter-clockwise.
+* Tests that geometry is oriented LW_CLOCKWISE or LW_COUNTERCLOCKWISE.
+* Ensure the outer ring is oriented and all inner rings
+* are anti-oriented. Returns LW_TRUE for oriented or non-orientable (empty
+* or non-polygonal geometry) and LW_FALSE for misoriented.
*/
-extern int lwgeom_is_clockwise(LWGEOM *lwgeom);
+extern int lwgeom_has_orientation(const LWGEOM *lwgeom, int orientation);
/**
@@ -1427,6 +1429,7 @@ extern void lwgeom_grid_in_place(LWGEOM *lwgeom, gridspec *grid);
extern void lwgeom_reverse_in_place(LWGEOM *lwgeom);
extern void lwgeom_force_clockwise(LWGEOM *lwgeom);
+extern void lwgeom_force_counterclockwise(LWGEOM *lwgeom);
extern void lwgeom_longitude_shift(LWGEOM *lwgeom);
extern int lwgeom_simplify_in_place(LWGEOM *igeom, double dist, int preserve_collapsed);
extern void lwgeom_affine(LWGEOM *geom, const AFFINE *affine);
diff --git a/liblwgeom/liblwgeom_internal.h b/liblwgeom/liblwgeom_internal.h
index 04a3504e2..39baf8032 100644
--- a/liblwgeom/liblwgeom_internal.h
+++ b/liblwgeom/liblwgeom_internal.h
@@ -157,6 +157,13 @@
#define LW_BOUNDARY 0
#define LW_OUTSIDE -1
+/**
+* Constants for orientation checking and forcing
+*/
+#define LW_CLOCKWISE 1
+#define LW_NONE 0
+#define LW_COUNTERCLOCKWISE -1
+
/*
* Internal prototypes
*/
@@ -361,12 +368,13 @@ LWCOLLECTION *lwcollection_clone_deep(const LWCOLLECTION *lwgeom);
GBOX *gbox_clone(const GBOX *gbox);
/*
-* Clockwise
+* Orientation (LW_CLOCKWISE and LW_COUNTERCLOCKWISE)
*/
-void lwpoly_force_clockwise(LWPOLY *poly);
-void lwtriangle_force_clockwise(LWTRIANGLE *triangle);
-int lwpoly_is_clockwise(LWPOLY *poly);
-int lwtriangle_is_clockwise(LWTRIANGLE *triangle);
+void lwpoly_force_orientation(LWPOLY *poly, int orientation);
+void lwtriangle_force_orientation(LWTRIANGLE *triangle, int orientation);
+int lwpoly_has_orientation(const LWPOLY *poly, int orientation);
+int lwtriangle_has_orientation(const LWTRIANGLE *triangle, int orientation);
+int ptarray_has_orientation(const POINTARRAY *pa, int orientation);
int ptarray_isccw(const POINTARRAY *pa);
/*
diff --git a/liblwgeom/lwgeom.c b/liblwgeom/lwgeom.c
index 6697186d8..a2d65dc0f 100644
--- a/liblwgeom/lwgeom.c
+++ b/liblwgeom/lwgeom.c
@@ -33,61 +33,89 @@
#define out_stack_size 32
-/** Force Right-hand-rule on LWGEOM polygons **/
-void
-lwgeom_force_clockwise(LWGEOM *lwgeom)
-{
- LWCOLLECTION *coll;
- uint32_t i;
- switch (lwgeom->type)
- {
- case POLYGONTYPE:
- lwpoly_force_clockwise((LWPOLY *)lwgeom);
- return;
-
- case TRIANGLETYPE:
- lwtriangle_force_clockwise((LWTRIANGLE *)lwgeom);
- return;
-
- /* Not handle POLYHEDRALSURFACE and TIN
- as they are supposed to be well oriented */
- case MULTIPOLYGONTYPE:
- case COLLECTIONTYPE:
- coll = (LWCOLLECTION *)lwgeom;
- for (i=0; i<coll->ngeoms; i++)
- lwgeom_force_clockwise(coll->geoms[i]);
- return;
- }
-}
-
-/** Check clockwise orientation on LWGEOM polygons **/
-int
-lwgeom_is_clockwise(LWGEOM *lwgeom)
+/**
+ * Force an orientation onto geometries made up of rings,
+ * so the rings circle in a particular direction, clockwise
+ * or counter-clockwise. The orientation is one of
+ * LW_CLOCKWISE or LW_COUNTERCLOCKWISE. Non-polygonal
+ * geometries are ignored and returned untouched.
+ */
+static void
+lwgeom_force_orientation(LWGEOM *lwgeom, int orientation)
{
switch (lwgeom->type)
{
case POLYGONTYPE:
- return lwpoly_is_clockwise((LWPOLY *)lwgeom);
+ lwpoly_force_orientation(lwgeom_as_lwpoly(lwgeom), orientation);
+ return;
case TRIANGLETYPE:
- return lwtriangle_is_clockwise((LWTRIANGLE *)lwgeom);
+ lwtriangle_force_orientation(lwgeom_as_lwtriangle(lwgeom), orientation);
+ return;
+
+ /* Not handle POLYHEDRALSURFACE and TIN
+ as they are supposed to be well oriented */
+ case MULTIPOLYGONTYPE:
+ case COLLECTIONTYPE:
+ {
+ LWCOLLECTION* coll = lwgeom_as_lwcollection(lwgeom);
+ for (uint32_t i = 0; coll && i < coll->ngeoms; i++)
+ {
+ lwgeom_force_orientation(coll->geoms[i], orientation);
+ }
+ return;
+ }
+ }
+}
+
+void
+lwgeom_force_clockwise(LWGEOM *lwgeom)
+{
+ return lwgeom_force_orientation(lwgeom, LW_CLOCKWISE);
+}
+
+void
+lwgeom_force_counterclockwise(LWGEOM *lwgeom)
+{
+ return lwgeom_force_orientation(lwgeom, LW_COUNTERCLOCKWISE);
+}
+
+
+/**
+ * Check clockwise orientation on LWGEOM polygons
+ * returns LW_CLOCKWISE, LW_NONE, LW_COUNTERCLOCKWISE
+ * Non-polygonal geometries return LW_NONE
+ * Geometries must have *all* rings correctly oriented
+ * to return a non-none orientation
+ */
+int
+lwgeom_has_orientation(const LWGEOM *lwgeom, int orientation)
+{
+ switch (lwgeom->type)
+ {
+ case POLYGONTYPE:
+ return lwpoly_has_orientation(lwgeom_as_lwpoly(lwgeom), orientation);
+
+ case TRIANGLETYPE:
+ return lwtriangle_has_orientation(lwgeom_as_lwtriangle(lwgeom), orientation);
case MULTIPOLYGONTYPE:
case COLLECTIONTYPE:
{
- uint32_t i;
- LWCOLLECTION* coll = (LWCOLLECTION *)lwgeom;
-
- for (i=0; i < coll->ngeoms; i++)
- if (!lwgeom_is_clockwise(coll->geoms[i]))
+ LWCOLLECTION* coll = lwgeom_as_lwcollection(lwgeom);
+ for (uint32_t i = 0; coll && i < coll->ngeoms; i++)
+ {
+ if(!lwgeom_has_orientation(coll->geoms[i], orientation))
return LW_FALSE;
+ }
return LW_TRUE;
}
+
default:
return LW_TRUE;
- return LW_FALSE;
}
+ return LW_FALSE;
}
LWGEOM *
@@ -1178,7 +1206,7 @@ lwtype_is_collection(uint8_t type)
case MULTICURVETYPE:
case MULTISURFACETYPE:
case POLYHEDRALSURFACETYPE:
- case TINTYPE:
+ case TINTYPE:
return LW_TRUE;
break;
diff --git a/liblwgeom/lwpoly.c b/liblwgeom/lwpoly.c
index 145e2cc75..a4949e734 100644
--- a/liblwgeom/lwpoly.c
+++ b/liblwgeom/lwpoly.c
@@ -265,38 +265,37 @@ lwpoly_add_ring(LWPOLY *poly, POINTARRAY *pa)
}
void
-lwpoly_force_clockwise(LWPOLY *poly)
+lwpoly_force_orientation(LWPOLY *poly, int orientation)
{
- uint32_t i;
+ /* No-op no orientation */
+ if (orientation == LW_NONE) return;
/* No-op empties */
- if ( lwpoly_is_empty(poly) )
- return;
+ if (lwpoly_is_empty(poly)) return;
/* External ring */
- if ( ptarray_isccw(poly->rings[0]) )
+ if (!ptarray_has_orientation(poly->rings[0], orientation))
ptarray_reverse_in_place(poly->rings[0]);
- /* Internal rings */
- for (i=1; i<poly->nrings; i++)
- if ( ! ptarray_isccw(poly->rings[i]) )
+ /* Internal rings must run opposite to external */
+ for (uint32_t i = 1; i < poly->nrings; i++)
+ if (!ptarray_has_orientation(poly->rings[i], -1 * orientation))
ptarray_reverse_in_place(poly->rings[i]);
-
}
int
-lwpoly_is_clockwise(LWPOLY *poly)
+lwpoly_has_orientation(const LWPOLY *poly, int orientation)
{
- uint32_t i;
-
- if ( lwpoly_is_empty(poly) )
+ if (lwpoly_is_empty(poly))
return LW_TRUE;
- if ( ptarray_isccw(poly->rings[0]) )
+ /* Exterior ring matches orientation? */
+ if(!ptarray_has_orientation(poly->rings[0], orientation))
return LW_FALSE;
- for ( i = 1; i < poly->nrings; i++)
- if ( !ptarray_isccw(poly->rings[i]) )
+ /* Interior rings are opposite of orientation? */
+ for (uint32_t i = 1; i < poly->nrings; i++)
+ if (!ptarray_has_orientation(poly->rings[i], -1 * orientation))
return LW_FALSE;
return LW_TRUE;
diff --git a/liblwgeom/lwtriangle.c b/liblwgeom/lwtriangle.c
index adfa9c04f..b37279077 100644
--- a/liblwgeom/lwtriangle.c
+++ b/liblwgeom/lwtriangle.c
@@ -102,17 +102,17 @@ lwtriangle_clone(const LWTRIANGLE *g)
return (LWTRIANGLE *)lwline_clone((const LWLINE *)g);
}
-void
-lwtriangle_force_clockwise(LWTRIANGLE *triangle)
+int
+lwtriangle_has_orientation(const LWTRIANGLE *triangle, int orientation)
{
- if ( ptarray_isccw(triangle->points) )
- ptarray_reverse_in_place(triangle->points);
+ return ptarray_has_orientation(triangle->points, orientation);
}
-int
-lwtriangle_is_clockwise(LWTRIANGLE *triangle)
+void
+lwtriangle_force_orientation(LWTRIANGLE *triangle, int orientation)
{
- return !ptarray_isccw(triangle->points);
+ if (!lwtriangle_has_orientation(triangle, orientation))
+ ptarray_reverse_in_place(triangle->points);
}
void
diff --git a/liblwgeom/ptarray.c b/liblwgeom/ptarray.c
index 4bf5816e9..cce30d5b2 100644
--- a/liblwgeom/ptarray.c
+++ b/liblwgeom/ptarray.c
@@ -1171,12 +1171,17 @@ ptarray_signed_area(const POINTARRAY *pa)
}
int
-ptarray_isccw(const POINTARRAY *pa)
+ptarray_has_orientation(const POINTARRAY *pa, int orientation)
{
- double area = 0;
- area = ptarray_signed_area(pa);
- if ( area > 0 ) return LW_FALSE;
- else return LW_TRUE;
+ if (ptarray_signed_area(pa) > 0)
+ return orientation == LW_CLOCKWISE;
+ else
+ return orientation == LW_COUNTERCLOCKWISE;
+}
+
+int ptarray_isccw(const POINTARRAY *pa)
+{
+ return ptarray_has_orientation(pa, LW_COUNTERCLOCKWISE);
}
POINTARRAY*
diff --git a/postgis/lwgeom_functions_analytic.c b/postgis/lwgeom_functions_analytic.c
index abcc222c6..13e31cf01 100644
--- a/postgis/lwgeom_functions_analytic.c
+++ b/postgis/lwgeom_functions_analytic.c
@@ -869,21 +869,12 @@ PG_FUNCTION_INFO_V1(ST_IsPolygonCW);
Datum ST_IsPolygonCW(PG_FUNCTION_ARGS)
{
GSERIALIZED* geom;
- LWGEOM* input;
- bool is_clockwise;
if (PG_ARGISNULL(0))
PG_RETURN_NULL();
geom = PG_GETARG_GSERIALIZED_P(0);
- input = lwgeom_from_gserialized(geom);
-
- is_clockwise = lwgeom_is_clockwise(input);
-
- lwgeom_free(input);
- PG_FREE_IF_COPY(geom, 0);
-
- PG_RETURN_BOOL(is_clockwise);
+ PG_RETURN_BOOL(lwgeom_has_orientation(lwgeom_from_gserialized(geom), LW_CLOCKWISE));
}
/**********************************************************************
@@ -896,19 +887,12 @@ PG_FUNCTION_INFO_V1(ST_IsPolygonCCW);
Datum ST_IsPolygonCCW(PG_FUNCTION_ARGS)
{
GSERIALIZED* geom;
- LWGEOM* input;
- bool is_ccw;
if (PG_ARGISNULL(0))
PG_RETURN_NULL();
- geom = PG_GETARG_GSERIALIZED_P_COPY(0);
- input = lwgeom_from_gserialized(geom);
- lwgeom_reverse_in_place(input);
- is_ccw = lwgeom_is_clockwise(input);
- lwgeom_free(input);
- PG_FREE_IF_COPY(geom, 0);
-
- PG_RETURN_BOOL(is_ccw);
+ geom = PG_GETARG_GSERIALIZED_P(0);
+ geom = PG_GETARG_GSERIALIZED_P(0);
+ PG_RETURN_BOOL(lwgeom_has_orientation(lwgeom_from_gserialized(geom), LW_COUNTERCLOCKWISE));
}
diff --git a/postgis/lwgeom_functions_basic.c b/postgis/lwgeom_functions_basic.c
index 06ea00934..b3e1179b3 100644
--- a/postgis/lwgeom_functions_basic.c
+++ b/postgis/lwgeom_functions_basic.c
@@ -1934,6 +1934,31 @@ Datum LWGEOM_force_clockwise_poly(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(outgeom);
}
+
+/**
+ * Force polygon exterior rings to circle counter-clockwise,
+ * and interior rings to circle clockwise.
+ */
+PG_FUNCTION_INFO_V1(ST_ForcePolygonCCW);
+Datum ST_ForcePolygonCCW(PG_FUNCTION_ARGS)
+{
+ GSERIALIZED *ingeom, *outgeom;
+ LWGEOM *lwgeom;
+
+ POSTGIS_DEBUG(2, "ST_ForcePolygonCCW called");
+
+ ingeom = PG_GETARG_GSERIALIZED_P_COPY(0);
+
+ lwgeom = lwgeom_from_gserialized(ingeom);
+ lwgeom_force_counterclockwise(lwgeom);
+
+ outgeom = geometry_serialize(lwgeom);
+
+ lwgeom_free(lwgeom);
+ PG_FREE_IF_COPY(ingeom, 0);
+ PG_RETURN_POINTER(outgeom);
+}
+
/** Test deserialize/serialize operations */
PG_FUNCTION_INFO_V1(LWGEOM_noop);
Datum LWGEOM_noop(PG_FUNCTION_ARGS)
diff --git a/postgis/postgis.sql.in b/postgis/postgis.sql.in
index 03a7fdde8..f508024c5 100644
--- a/postgis/postgis.sql.in
+++ b/postgis/postgis.sql.in
@@ -1592,10 +1592,11 @@ CREATE OR REPLACE FUNCTION ST_ForcePolygonCW(geometry)
_COST_LOW;
-- Availability: 2.4.0
+-- Changed: 3.7.0 - C implementation
CREATE OR REPLACE FUNCTION ST_ForcePolygonCCW(geometry)
RETURNS geometry
- AS $$ SELECT @extschema at .ST_Reverse(@extschema at .ST_ForcePolygonCW($1)) $$
- LANGUAGE 'sql' IMMUTABLE STRICT PARALLEL SAFE
+ AS 'MODULE_PATHNAME', 'ST_ForcePolygonCCW'
+ LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE
_COST_LOW;
-- Availability: 1.2.2
diff --git a/regress/core/tickets.sql b/regress/core/tickets.sql
index 4b580b003..cffa4fbf8 100644
--- a/regress/core/tickets.sql
+++ b/regress/core/tickets.sql
@@ -1623,3 +1623,9 @@ SELECT '#5962',
ST_AsText(ST_ClipByBox2D(
ST_GeomFromText('MULTIPOINT((1 1),(6 4),(5 4))'),
ST_MakeEnvelope(0, 0, 5, 5 )), 2);
+
+SELECT '#5754' AS Ticket,
+ ST_AsText(ST_ForcePolygonCCW('LINESTRING(0 0, 1 1, 2 0, 3 1, 4 0)'::geometry), 1) AS LsCcw,
+ ST_AsText(ST_ForcePolygonCW('LINESTRING(0 0, 1 1, 2 0, 3 1, 4 0)'::geometry), 1) AS LsCw,
+ ST_AsText(ST_ForcePolygonCCW('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))'::geometry), 1) AS PlyCcw1,
+ ST_AsText(ST_ForcePolygonCCW('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0),(1 1, 2 1, 2 2, 1 2, 1 1))'::geometry), 1) AS PlyCcw2
diff --git a/regress/core/tickets_expected b/regress/core/tickets_expected
index 0f2bf2f39..98d74a836 100644
--- a/regress/core/tickets_expected
+++ b/regress/core/tickets_expected
@@ -492,3 +492,4 @@ public|test5978|geometry|2|4326|POINT
public|test5978|shape|2|4326|POINT
#5987|LINESTRING(20 20,20.1 20,20.2 19.9)|LINESTRING(20 20,20.1 20,20.2 19.9)
#5962|MULTIPOINT((1 1),(3 4))|POINT(1 1)
+#5754|LINESTRING(0 0,1 1,2 0,3 1,4 0)|LINESTRING(0 0,1 1,2 0,3 1,4 0)|POLYGON((0 0,1 0,1 1,0 1,0 0))|POLYGON((0 0,10 0,10 10,0 10,0 0),(1 1,1 2,2 2,2 1,1 1))
-----------------------------------------------------------------------
Summary of changes:
liblwgeom/cunit/cu_gserialized1.c | 16 ++++---
liblwgeom/liblwgeom.h.in | 9 ++--
liblwgeom/liblwgeom_internal.h | 18 +++++---
liblwgeom/lwgeom.c | 86 ++++++++++++++++++++++++-------------
liblwgeom/lwpoly.c | 31 +++++++------
liblwgeom/lwtriangle.c | 14 +++---
liblwgeom/ptarray.c | 15 ++++---
postgis/lwgeom_functions_analytic.c | 24 ++---------
postgis/lwgeom_functions_basic.c | 25 +++++++++++
postgis/postgis.sql.in | 5 ++-
regress/core/tickets.sql | 6 +++
regress/core/tickets_expected | 1 +
12 files changed, 157 insertions(+), 93 deletions(-)
hooks/post-receive
--
PostGIS
More information about the postgis-tickets
mailing list