Commit 7915c4cb authored by Darafei Praliaskouski's avatar Darafei Praliaskouski

ST_LocateBetween[Elevations]: support TIN and TRIANGLE clipping.

Triangle is converted into a TIN that has several triangles with same orientation.

Committed in Paris Airport.

Closes #4155


git-svn-id: http://svn.osgeo.org/postgis/trunk@16954 b70326c6-7e19-0410-871a-916f4a2858ee
parent 7538e459
Pipeline #34523819 passed with stage
in 32 minutes and 49 seconds
......@@ -27,8 +27,8 @@ PostGIS 3.0.0
Praliaskouski)
- #3457, Fix raster envelope shortcut in ST_Clip (Sai-bot)
- #4215, Use floating point compare in ST_DumpAsPolygons (Darafei Praliaskouski)
- #4155, Support for GEOMETRYCOLLECTION and POLYGON in ST_LocateBetween (Darafei
Praliaskouski)
- #4155, Support for GEOMETRYCOLLECTION, POLYGON, TIN, TRIANGLE in
ST_LocateBetween and ST_LocateBetweenElevations (Darafei Praliaskouski)
PostGIS 2.5.0
2018/09/23
......
......@@ -426,15 +426,14 @@ SELECT ST_AsText((ST_Dump(the_geom)).geom)
<refname>ST_LocateBetween</refname>
<refpurpose>Return a derived geometry collection value with elements
that match the specified range of measures inclusively. Polygonal
elements are not supported.</refpurpose>
that match the specified range of measures inclusively.</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
<funcprototype>
<funcdef>geometry <function>ST_LocateBetween</function></funcdef>
<paramdef><type>geometry </type> <parameter>geomA</parameter></paramdef>
<paramdef><type>geometry </type> <parameter>geom</parameter></paramdef>
<paramdef><type>float8 </type> <parameter>measure_start</parameter></paramdef>
<paramdef><type>float8 </type> <parameter>measure_end</parameter></paramdef>
<paramdef choice="opt"><type>float8 </type> <parameter>offset</parameter></paramdef>
......@@ -447,7 +446,9 @@ SELECT ST_AsText((ST_Dump(the_geom)).geom)
<title>Description</title>
<para>Return a derived geometry collection with elements that match the specified range of
measures inclusively. Polygonal elements are not supported.</para>
measures inclusively.</para>
<para>Clipping a non-convex POLYGON may produce invalid geometry.</para>
<para>If an offset is provided, the resultant will be offset to the left or right of the
input line by the specified number of units. A positive offset will be to the left, and
......@@ -458,6 +459,7 @@ SELECT ST_AsText((ST_Dump(the_geom)).geom)
<para>Availability: 1.1.0 by old name ST_Locate_Between_Measures. </para>
<para>Changed: 2.0.0 - in prior versions this used to be called ST_Locate_Between_Measures. The old name has been deprecated and will be removed in the future but is still available for backward compatibility.</para>
<para>Enhanced: 3.0.0 - added support for POLYGON, TIN, TRIANGLE.</para>
<para>&M_support;</para>
</refsection>
......@@ -465,11 +467,15 @@ SELECT ST_AsText((ST_Dump(the_geom)).geom)
<refsection>
<title>Examples</title>
<programlisting>SELECT ST_AsText(the_geom)
FROM
(SELECT ST_LocateBetween(
ST_GeomFromText('MULTILINESTRING M ((1 2 3, 3 4 2, 9 4 3),
(1 2 3, 5 4 5))'),1.5, 3) As the_geom) As foo;
<programlisting>
SELECT ST_AsText(the_geom)
FROM (
SELECT ST_LocateBetween(
'MULTILINESTRING M ((1 2 3, 3 4 2, 9 4 3),(1 2 3, 5 4 5))'),
1.5,
3
) as the_geom
) As foo;
st_asewkt
------------------------------------------------------------------------
......@@ -478,10 +484,13 @@ SELECT ST_AsText((ST_Dump(the_geom)).geom)
--Geometry collections are difficult animals so dump them
--to make them more digestable
SELECT ST_AsText((ST_Dump(the_geom)).geom)
FROM
(SELECT ST_LocateBetween(
ST_GeomFromText('MULTILINESTRING M ((1 2 3, 3 4 2, 9 4 3),
(1 2 3, 5 4 5))'),1.5, 3) As the_geom) As foo;
FROM (
SELECT ST_LocateBetween(
'MULTILINESTRING M ((1 2 3, 3 4 2, 9 4 3),(1 2 3, 5 4 5))'),
1.5,
3
) As the_geom
) As foo;
st_asewkt
--------------------------------
......@@ -502,15 +511,14 @@ SELECT ST_AsText((ST_Dump(the_geom)).geom)
<refname>ST_LocateBetweenElevations</refname>
<refpurpose>Return a derived geometry (collection) value with elements
that intersect the specified range of elevations inclusively. Only 3D, 4D LINESTRINGS and MULTILINESTRINGS
are supported.</refpurpose>
that intersect the specified range of elevations inclusively.</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
<funcprototype>
<funcdef>geometry <function>ST_LocateBetweenElevations</function></funcdef>
<paramdef><type>geometry </type> <parameter>geom_mline</parameter></paramdef>
<paramdef><type>geometry </type> <parameter>geom</parameter></paramdef>
<paramdef><type>float8 </type> <parameter>elevation_start</parameter></paramdef>
<paramdef><type>float8 </type> <parameter>elevation_end</parameter></paramdef>
</funcprototype>
......@@ -521,11 +529,13 @@ SELECT ST_AsText((ST_Dump(the_geom)).geom)
<refsection>
<title>Description</title>
<para>Return a derived geometry (collection) value with elements
that intersect the specified range of elevations inclusively. Only 3D, 3DM LINESTRINGS and MULTILINESTRINGS
are supported.</para>
<para>Return a derived geometry (collection) value with elements
that intersect the specified range of elevations inclusively.</para>
<para>Availability: 1.4.0</para>
<para>Clipping a non-convex POLYGON may produce invalid geometry.</para>
<para>Availability: 1.4.0</para>
<para>Enhanced: 3.0.0 - added support for POLYGON, TIN, TRIANGLE.</para>
<para>&Z_support;</para>
</refsection>
......@@ -534,24 +544,22 @@ SELECT ST_AsText((ST_Dump(the_geom)).geom)
<title>Examples</title>
<programlisting>SELECT ST_AsEWKT(ST_LocateBetweenElevations(
ST_GeomFromEWKT('LINESTRING(1 2 3, 4 5 6)'),2,4)) As ewelev;
ST_GeomFromEWKT('LINESTRING(1 2 3, 4 5 6)'), 2, 4)) As ewelev;
ewelev
----------------------------------------------------------------
MULTILINESTRING((1 2 3,2 3 4))
SELECT ST_AsEWKT(ST_LocateBetweenElevations(
ST_GeomFromEWKT('LINESTRING(1 2 6, 4 5 -1, 7 8 9)'),6,9)) As ewelev;
SELECT ST_AsEWKT(ST_LocateBetweenElevations('LINESTRING(1 2 6, 4 5 -1, 7 8 9)', 6, 9)) As ewelev;
ewelev
----------------------------------------------------------------
GEOMETRYCOLLECTION(POINT(1 2 6),LINESTRING(6.1 7.1 6,7 8 9))
--Geometry collections are difficult animals so dump them
--to make them more digestable
-- Geometry collections are difficult animals so dump them
-- to make them more digestable
SELECT ST_AsEWKT((ST_Dump(the_geom)).geom)
FROM
(SELECT ST_LocateBetweenElevations(
ST_GeomFromEWKT('LINESTRING(1 2 6, 4 5 -1, 7 8 9)'),6,9) As the_geom) As foo;
FROM
(SELECT ST_LocateBetweenElevations('LINESTRING(1 2 6, 4 5 -1, 7 8 9)', 6, 9) as the_geom) As foo;
st_asewkt
--------------------------------
......@@ -564,7 +572,7 @@ LINESTRING(6.1 7.1 6,7 8 9)
<refsection>
<title>See Also</title>
<para><xref linkend="ST_Dump" /></para>
<para><xref linkend="ST_Dump" />, <xref linkend="ST_LocateBetween" /></para>
</refsection>
</refentry>
......
This diff is collapsed.
......@@ -440,7 +440,7 @@ lwmpoint_clip_to_ordinate_range(const LWMPOINT *mpoint, char ordinate, double fr
}
static inline POINTARRAY *
ptarray_clamp_to_ordinate_range(const POINTARRAY *ipa, char ordinate, double from, double to)
ptarray_clamp_to_ordinate_range(const POINTARRAY *ipa, char ordinate, double from, double to, uint8_t is_closed)
{
POINT4D p1, p2;
POINTARRAY *opa;
......@@ -524,7 +524,7 @@ ptarray_clamp_to_ordinate_range(const POINTARRAY *ipa, char ordinate, double fro
LW_ON_INTERRUPT(ptarray_free(opa); return NULL);
}
if (ptarray_is_closed(ipa) && opa->npoints > 0)
if (is_closed && opa->npoints > 2)
{
getPoint4d_p(opa, 0, &p1);
ptarray_append_point(opa, &p1, LW_FALSE);
......@@ -769,7 +769,7 @@ lwpoly_clip_to_ordinate_range(const LWPOLY *poly, char ordinate, double from, do
for (i = 0; i < nrings; i++)
{
/* Ret number of points */
POINTARRAY *pa = ptarray_clamp_to_ordinate_range(poly->rings[i], ordinate, from, to);
POINTARRAY *pa = ptarray_clamp_to_ordinate_range(poly->rings[i], ordinate, from, to, LW_TRUE);
if (pa->npoints >= 4)
lwpoly_add_ring(poly_res, pa);
......@@ -785,6 +785,41 @@ lwpoly_clip_to_ordinate_range(const LWPOLY *poly, char ordinate, double from, do
return lwgeom_out;
}
/**
* Clip an input LWTRIANGLE between two values, on any ordinate input.
*/
static inline LWCOLLECTION *
lwtriangle_clip_to_ordinate_range(const LWTRIANGLE *tri, char ordinate, double from, double to)
{
LWCOLLECTION *lwgeom_out = NULL;
char hasz = FLAGS_GET_Z(tri->flags), hasm = FLAGS_GET_M(tri->flags);
assert(tri);
lwgeom_out = lwcollection_construct_empty(TINTYPE, tri->srid, hasz, hasm);
POINTARRAY *pa = ptarray_clamp_to_ordinate_range(tri->points, ordinate, from, to, LW_TRUE);
if (pa->npoints >= 4)
{
POINT4D first = getPoint4d(pa, 0);
for (uint32_t i = 1; i < pa->npoints - 2; i++)
{
POINT4D p;
POINTARRAY *tpa = ptarray_construct_empty(hasz, hasm, 4);
ptarray_append_point(tpa, &first, LW_TRUE);
getPoint4d_p(pa, i, &p);
ptarray_append_point(tpa, &p, LW_TRUE);
getPoint4d_p(pa, i + 1, &p);
ptarray_append_point(tpa, &p, LW_TRUE);
ptarray_append_point(tpa, &first, LW_TRUE);
LWTRIANGLE *otri = lwtriangle_construct(tri->srid, NULL, tpa);
lwgeom_out = lwcollection_add_lwgeom(lwgeom_out, (LWGEOM *)otri);
}
}
ptarray_free(pa);
return lwgeom_out;
}
/**
* Clip an input COLLECTION between two values, on any ordinate input.
*/
......@@ -859,9 +894,9 @@ lwgeom_clip_to_ordinate_range(const LWGEOM *lwin, char ordinate, double from, do
case POLYGONTYPE:
out_col = lwpoly_clip_to_ordinate_range((LWPOLY *)lwin, ordinate, from, to);
break;
// case TRIANGLETYPE:
// out_col = lwtriangle_clip_to_ordinate_range((LWTRIANGLE*)lwin, ordinate, from, to);
// break;
case TRIANGLETYPE:
out_col = lwtriangle_clip_to_ordinate_range((LWTRIANGLE *)lwin, ordinate, from, to);
break;
case TINTYPE:
case MULTILINETYPE:
case MULTIPOLYGONTYPE:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment