p.z = 0.0;
p.m = 0.0;
- lwpoint_set_ordinate(&p, 0, 1.5);
+ lwpoint_set_ordinate(&p, 'X', 1.5);
CU_ASSERT_EQUAL( p.x, 1.5 );
- lwpoint_set_ordinate(&p, 3, 2.5);
+ lwpoint_set_ordinate(&p, 'M', 2.5);
CU_ASSERT_EQUAL( p.m, 2.5 );
- lwpoint_set_ordinate(&p, 2, 3.5);
+ lwpoint_set_ordinate(&p, 'Z', 3.5);
CU_ASSERT_EQUAL( p.z, 3.5 );
}
p.z = 30.0;
p.m = 40.0;
- CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 0), 10.0 );
- CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 1), 20.0 );
- CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 2), 30.0 );
- CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 3), 40.0 );
+ CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 'X'), 10.0 );
+ CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 'Y'), 20.0 );
+ CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 'Z'), 30.0 );
+ CU_ASSERT_EQUAL( lwpoint_get_ordinate(&p, 'M'), 40.0 );
}
q.z = 40.0;
q.m = 50.0;
- rv = lwpoint_interpolate(&p, &q, &r, 4, 2, 35.0);
+ rv = lwpoint_interpolate(&p, &q, &r, 1, 1, 'Z', 35.0);
CU_ASSERT_EQUAL( r.x, 15.0);
- rv = lwpoint_interpolate(&p, &q, &r, 4, 3, 41.0);
+ rv = lwpoint_interpolate(&p, &q, &r, 1, 1, 'M', 41.0);
CU_ASSERT_EQUAL( r.y, 21.0);
- rv = lwpoint_interpolate(&p, &q, &r, 4, 3, 50.0);
+ rv = lwpoint_interpolate(&p, &q, &r, 1, 1, 'M', 50.0);
CU_ASSERT_EQUAL( r.y, 30.0);
- rv = lwpoint_interpolate(&p, &q, &r, 4, 3, 40.0);
+ rv = lwpoint_interpolate(&p, &q, &r, 1, 1, 'M', 40.0);
CU_ASSERT_EQUAL( r.y, 20.0);
}
l51 = (LWLINE*)lwgeom_from_wkt("LINESTRING(0 0, 0 1, 0 2, 0 3, 0 4)", LW_PARSER_CHECK_NONE);
/* Clip in the middle, mid-range. */
- c = lwline_clip_to_ordinate_range(l51, 1, 1.5, 2.5);
+ c = lwline_clip_to_ordinate_range(l51, 'Y', 1.5, 2.5);
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
//printf("c = %s\n", ewkt);
CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1.5,0 2,0 2.5))");
lwcollection_free(c);
/* Clip off the top. */
- c = lwline_clip_to_ordinate_range(l51, 1, 3.5, 5.5);
+ c = lwline_clip_to_ordinate_range(l51, 'Y', 3.5, 5.5);
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
//printf("c = %s\n", ewkt);
CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 3.5,0 4))");
lwcollection_free(c);
/* Clip off the bottom. */
- c = lwline_clip_to_ordinate_range(l51, 1, -1.5, 2.5);
+ c = lwline_clip_to_ordinate_range(l51, 'Y', -1.5, 2.5);
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
//printf("c = %s\n", ewkt);
CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 0,0 1,0 2,0 2.5))" );
lwcollection_free(c);
/* Range holds entire object. */
- c = lwline_clip_to_ordinate_range(l51, 1, -1.5, 5.5);
+ c = lwline_clip_to_ordinate_range(l51, 'Y', -1.5, 5.5);
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
//printf("c = %s\n", ewkt);
CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 0,0 1,0 2,0 3,0 4))" );
lwcollection_free(c);
/* Clip on vertices. */
- c = lwline_clip_to_ordinate_range(l51, 1, 1.0, 2.0);
+ c = lwline_clip_to_ordinate_range(l51, 'Y', 1.0, 2.0);
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
//printf("c = %s\n", ewkt);
CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1,0 2))" );
lwcollection_free(c);
/* Clip on vertices off the bottom. */
- c = lwline_clip_to_ordinate_range(l51, 1, -1.0, 2.0);
+ c = lwline_clip_to_ordinate_range(l51, 'Y', -1.0, 2.0);
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
//printf("c = %s\n", ewkt);
CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 0,0 1,0 2))" );
lwcollection_free(c);
/* Clip on top. */
- c = lwline_clip_to_ordinate_range(l51, 1, -1.0, 0.0);
+ c = lwline_clip_to_ordinate_range(l51, 'Y', -1.0, 0.0);
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
//printf("c = %s\n", ewkt);
CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(0 0))" );
/* ST_LocateBetweenElevations(ST_GeomFromEWKT('LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)'), 1, 2)) */
line = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)", LW_PARSER_CHECK_NONE);
- c = lwline_clip_to_ordinate_range(line, 2, 1.0, 2.0);
+ c = lwline_clip_to_ordinate_range(line, 'Z', 1.0, 2.0);
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2,1 1 1))" );
lwfree(ewkt);
/* ST_LocateBetweenElevations('LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)', 1, 2)) */
line = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)", LW_PARSER_CHECK_NONE);
- c = lwline_clip_to_ordinate_range(line, 2, 1.0, 2.0);
+ c = lwline_clip_to_ordinate_range(line, 'Z', 1.0, 2.0);
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
//printf("a = %s\n", ewkt);
CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2,1 1 1))" );
/* ST_LocateBetweenElevations('LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)', 1, 1)) */
line = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 2 3, 4 5 6, 6 6 6, 1 1 1)", LW_PARSER_CHECK_NONE);
- c = lwline_clip_to_ordinate_range(line, 2, 1.0, 1.0);
+ c = lwline_clip_to_ordinate_range(line, 'Z', 1.0, 1.0);
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
//printf("b = %s\n", ewkt);
CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 1 1))" );
/* ST_LocateBetweenElevations('LINESTRING(1 1 1, 1 2 2)', 1,1) */
line = (LWLINE*)lwgeom_from_wkt("LINESTRING(1 1 1, 1 2 2)", LW_PARSER_CHECK_NONE);
- c = lwline_clip_to_ordinate_range(line, 2, 1.0, 1.0);
+ c = lwline_clip_to_ordinate_range(line, 'Z', 1.0, 1.0);
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
//printf("c = %s\n", ewkt);
CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 1 1))" );
mline = (LWMLINE*)lwgeom_from_wkt("MULTILINESTRING((0 0,0 1,0 2,0 3,0 4))", LW_PARSER_CHECK_NONE);
/* Clip in the middle, mid-range. */
- c = lwmline_clip_to_ordinate_range(mline, 1, 1.5, 2.5);
+ c = lwmline_clip_to_ordinate_range(mline, 'Y', 1.5, 2.5);
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
//printf("c = %s\n", ewkt);
CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1.5,0 2,0 2.5))");
mline = (LWMLINE*)lwgeom_from_wkt("MULTILINESTRING((1 0,1 1,1 2,1 3,1 4), (0 0,0 1,0 2,0 3,0 4))", LW_PARSER_CHECK_NONE);
/* Clip off the top. */
- c = lwmline_clip_to_ordinate_range(mline, 1, 3.5, 5.5);
+ c = lwmline_clip_to_ordinate_range(mline, 'Y', 3.5, 5.5);
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
//printf("c = %s\n", ewkt);
CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((1 3.5,1 4),(0 3.5,0 4))");
mline = (LWMLINE*)lwgeom_from_wkt("MULTILINESTRING((1 0,1 -1,1 -2,1 -3,1 -4), (0 0,0 1,0 2,0 3,0 4))", LW_PARSER_CHECK_NONE);
/* Clip from 0 upwards.. */
- c = lwmline_clip_to_ordinate_range(mline, 1, 0.0, 2.5);
+ c = lwmline_clip_to_ordinate_range(mline, 'Y', 0.0, 2.5);
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
//printf("c = %s\n", ewkt);
CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 0),LINESTRING(0 0,0 1,0 2,0 2.5))");
line = (LWLINE*)lwgeom_from_wkt("LINESTRING(0 0 0 0,1 1 1 1,2 2 2 2,3 3 3 3,4 4 4 4,3 3 3 5,2 2 2 6,1 1 1 7,0 0 0 8)", LW_PARSER_CHECK_NONE);
/* Clip from 3 to 3.5 */
- c = lwline_clip_to_ordinate_range(line, 2, 3.0, 3.5);
+ c = lwline_clip_to_ordinate_range(line, 'Z', 3.0, 3.5);
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
//printf("c = %s\n", ewkt);
CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((3 3 3 3,3.5 3.5 3.5 3.5),(3.5 3.5 3.5 4.5,3 3 3 5))");
lwcollection_free(c);
/* Clip from 2 to 3.5 */
- c = lwline_clip_to_ordinate_range(line, 2, 2.0, 3.5);
+ c = lwline_clip_to_ordinate_range(line, 'Z', 2.0, 3.5);
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
//printf("c = %s\n", ewkt);
CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2 2,3 3 3 3,3.5 3.5 3.5 3.5),(3.5 3.5 3.5 4.5,3 3 3 5,2 2 2 6))");
lwcollection_free(c);
/* Clip from 3 to 4 */
- c = lwline_clip_to_ordinate_range(line, 2, 3.0, 4.0);
+ c = lwline_clip_to_ordinate_range(line, 'Z', 3.0, 4.0);
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
//printf("c = %s\n", ewkt);
CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((3 3 3 3,4 4 4 4,3 3 3 5))");
lwcollection_free(c);
/* Clip from 2 to 3 */
- c = lwline_clip_to_ordinate_range(line, 2, 2.0, 3.0);
+ c = lwline_clip_to_ordinate_range(line, 'Z', 2.0, 3.0);
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
//printf("c = %s\n", ewkt);
CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((2 2 2 2,3 3 3 3),(3 3 3 5,2 2 2 6))");
p.z = 2.0;
ptarray_set_point4d(pa, 2, &p);
- c = lwline_clip_to_ordinate_range(line, 2, 0.5, 1.5);
+ c = lwline_clip_to_ordinate_range(line, 'Z', 0.5, 1.5);
ewkt = lwgeom_to_ewkt((LWGEOM*)c);
//printf("c = %s\n", ewkt);
CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0.5 0.5 0.5,1 1 1,1.5 1.5 1.5))" );
/**
* Given two lines, characterize how (and if) they cross each other
*/
-int lwline_crossing_direction(LWLINE *l1, LWLINE *l2);
+int lwline_crossing_direction(const LWLINE *l1, const LWLINE *l2);
+
+/**
+* Given a geometry clip based on the from/to range of one of its ordinates (x, y, z, m). Use for m- and z- clipping.
+*/
+LWCOLLECTION* lwgeom_clip_to_ordinate_range(const LWGEOM *lwin, char ordinate, double from, double to);
/**
* Clip a line based on the from/to range of one of its ordinates. Use for m- and z- clipping
*/
-LWCOLLECTION *lwline_clip_to_ordinate_range(LWLINE *line, int ordinate, double from, double to);
+LWCOLLECTION *lwline_clip_to_ordinate_range(const LWLINE *line, char ordinate, double from, double to);
/**
* Clip a multi-line based on the from/to range of one of its ordinates. Use for m- and z- clipping
*/
-LWCOLLECTION *lwmline_clip_to_ordinate_range(LWMLINE *mline, int ordinate, double from, double to);
+LWCOLLECTION *lwmline_clip_to_ordinate_range(const LWMLINE *mline, char ordinate, double from, double to);
/*
* Export functions
/*
* Get/Set an enumeratoed ordinate. (x,y,z,m)
*/
-double lwpoint_get_ordinate(const POINT4D *p, int ordinate);
-void lwpoint_set_ordinate(POINT4D *p, int ordinate, double value);
+double lwpoint_get_ordinate(const POINT4D *p, char ordinate);
+void lwpoint_set_ordinate(POINT4D *p, char ordinate, double value);
/*
* Generate an interpolated coordinate p given an interpolation value and ordinate to apply it to
*/
-int lwpoint_interpolate(const POINT4D *p1, const POINT4D *p2, POINT4D *p, int ndims, int ordinate, double interpolation_value);
+int lwpoint_interpolate(const POINT4D *p1, const POINT4D *p2, POINT4D *p, int hasz, int hasm, char ordinate, double interpolation_value);
/*
* Geohash
** LINE_MULTICROSS_END_SAME_FIRST_RIGHT = 3
**
*/
-int lwline_crossing_direction(LWLINE *l1, LWLINE *l2)
+int lwline_crossing_direction(const LWLINE *l1, const LWLINE *l2)
{
int i = 0, j = 0, rv = 0;
POINT2D p1, p2, q1, q2;
* @param ordinate number (1=x, 2=y, 3=z, 4=m)
* @return d value at that ordinate
*/
-double lwpoint_get_ordinate(const POINT4D *p, int ordinate)
+double lwpoint_get_ordinate(const POINT4D *p, char ordinate)
{
if ( ! p )
{
return 0.0;
}
- if ( ordinate > 3 || ordinate < 0 )
+ if ( ! ( ordinate == 'X' || ordinate == 'Y' || ordinate == 'Z' || ordinate == 'M' ) )
{
- lwerror("Cannot extract ordinate %d.", ordinate);
+ lwerror("Cannot extract %c ordinate.", ordinate);
return 0.0;
}
- if ( ordinate == 3 )
- return p->m;
- if ( ordinate == 2 )
- return p->z;
- if ( ordinate == 1 )
+ if ( ordinate == 'X' )
+ return p->x;
+ if ( ordinate == 'Y' )
return p->y;
+ if ( ordinate == 'Z' )
+ return p->z;
+ if ( ordinate == 'M' )
+ return p->m;
+ /* X */
return p->x;
}
* Given a point, ordinate number and value, set that ordinate on the
* point.
*/
-void lwpoint_set_ordinate(POINT4D *p, int ordinate, double value)
+void lwpoint_set_ordinate(POINT4D *p, char ordinate, double value)
{
if ( ! p )
{
return;
}
- if ( ordinate > 3 || ordinate < 0 )
+ if ( ! ( ordinate == 'X' || ordinate == 'Y' || ordinate == 'Z' || ordinate == 'M' ) )
{
- lwerror("Cannot extract ordinate %d.", ordinate);
+ lwerror("Cannot set %c ordinate.", ordinate);
return;
}
- LWDEBUGF(4, " setting ordinate %d to %g", ordinate, value);
+ LWDEBUGF(4, " setting ordinate %c to %g", ordinate, value);
switch ( ordinate )
{
- case 3:
- p->m = value;
- return;
- case 2:
- p->z = value;
+ case 'X':
+ p->x = value;
return;
- case 1:
+ case 'Y':
p->y = value;
return;
- case 0:
- p->x = value;
+ case 'Z':
+ p->z = value;
+ return;
+ case 'M':
+ p->m = value;
return;
}
}
* generate a new point that is proportionally between the input points,
* using the values in the provided dimension as the scaling factors.
*/
-int lwpoint_interpolate(const POINT4D *p1, const POINT4D *p2, POINT4D *p, int ndims, int ordinate, double interpolation_value)
+int lwpoint_interpolate(const POINT4D *p1, const POINT4D *p2, POINT4D *p, int hasz, int hasm, char ordinate, double interpolation_value)
{
+ static char* dims = "XYZM";
double p1_value = lwpoint_get_ordinate(p1, ordinate);
double p2_value = lwpoint_get_ordinate(p2, ordinate);
double proportion;
int i = 0;
- if ( ordinate < 0 || ordinate >= ndims )
+ if ( ! ( ordinate == 'X' || ordinate == 'Y' || ordinate == 'Z' || ordinate == 'M' ) )
{
- lwerror("Ordinate (%d) is not within ndims (%d).", ordinate, ndims);
+ lwerror("Cannot set %c ordinate.", ordinate);
return 0;
}
if ( FP_MIN(p1_value, p2_value) > interpolation_value ||
- FP_MAX(p1_value, p2_value) < interpolation_value )
+ FP_MAX(p1_value, p2_value) < interpolation_value )
{
lwerror("Cannot interpolate to a value (%g) not between the input points (%g, %g).", interpolation_value, p1_value, p2_value);
return 0;
proportion = fabs((interpolation_value - p1_value) / (p2_value - p1_value));
- for ( i = 0; i < ndims; i++ )
+ for ( i = 0; i < 4; i++ )
{
double newordinate = 0.0;
- p1_value = lwpoint_get_ordinate(p1, i);
- p2_value = lwpoint_get_ordinate(p2, i);
+ if ( dims[i] == 'Z' && ! hasz ) continue;
+ if ( dims[i] == 'M' && ! hasm ) continue;
+ p1_value = lwpoint_get_ordinate(p1, dims[i]);
+ p2_value = lwpoint_get_ordinate(p2, dims[i]);
newordinate = p1_value + proportion * (p2_value - p1_value);
- lwpoint_set_ordinate(p, i, newordinate);
- LWDEBUGF(4, " clip ordinate(%d) p1_value(%g) p2_value(%g) proportion(%g) newordinate(%g) ", i, p1_value, p2_value, proportion, newordinate );
+ lwpoint_set_ordinate(p, dims[i], newordinate);
+ LWDEBUGF(4, " clip ordinate(%c) p1_value(%g) p2_value(%g) proportion(%g) newordinate(%g) ", dims[i], p1_value, p2_value, proportion, newordinate );
}
return 1;
/**
* Clip an input MULTILINESTRING between two values, on any ordinate input.
*/
-LWCOLLECTION *lwmline_clip_to_ordinate_range(LWMLINE *mline, int ordinate, double from, double to)
+LWCOLLECTION*
+lwmline_clip_to_ordinate_range(const LWMLINE *mline, char ordinate, double from, double to)
{
LWCOLLECTION *lwgeom_out = NULL;
else
{
LWCOLLECTION *col;
- char hasz = FLAGS_GET_Z(mline->flags);
- char hasm = FLAGS_GET_M(mline->flags);
+ char hasz = lwgeom_has_z(lwmline_as_lwgeom(mline));
+ char hasm = lwgeom_has_m(lwmline_as_lwgeom(mline));
int i, j;
char homogeneous = 1;
size_t geoms_size = 0;
* Take in a LINESTRING and return a MULTILINESTRING of those portions of the
* LINESTRING between the from/to range for the specified ordinate (XYZM)
*/
-LWCOLLECTION *lwline_clip_to_ordinate_range(LWLINE *line, int ordinate, double from, double to)
+LWCOLLECTION*
+lwline_clip_to_ordinate_range(const LWLINE *line, char ordinate, double from, double to)
{
POINTARRAY *pa_in = NULL;
int added_last_point = 0;
POINT4D *p = NULL, *q = NULL, *r = NULL;
double ordinate_value_p = 0.0, ordinate_value_q = 0.0;
- char hasz = FLAGS_GET_Z(line->flags);
- char hasm = FLAGS_GET_M(line->flags);
+ char hasz = lwgeom_has_z(lwline_as_lwgeom(line));
+ char hasm = lwgeom_has_m(lwline_as_lwgeom(line));
char dims = FLAGS_NDIMS(line->flags);
/* Null input, nothing we can do. */
to = t;
}
- LWDEBUGF(4, "from = %g, to = %g, ordinate = %d", from, to, ordinate);
+ LWDEBUGF(4, "from = %g, to = %g, ordinate = %c", from, to, ordinate);
LWDEBUGF(4, "%s", lwgeom_to_ewkt((LWGEOM*)line));
/* Asking for an ordinate we don't have. Error. */
- if ( ordinate >= dims )
+ if ( (ordinate == 'Z' && ! hasz) || (ordinate == 'M' && ! hasm) )
{
lwerror("Cannot clip on ordinate %d in a %d-d geometry.", ordinate, dims);
return NULL;
{
double interpolation_value;
(ordinate_value_q > to) ? (interpolation_value = to) : (interpolation_value = from);
- rv = lwpoint_interpolate(q, p, r, dims, ordinate, interpolation_value);
+ rv = lwpoint_interpolate(q, p, r, hasz, hasm, ordinate, interpolation_value);
rv = ptarray_append_point(dp, r, LW_FALSE);
LWDEBUGF(4, "[0] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
}
* to the point array at the range boundary. */
double interpolation_value;
(ordinate_value_p > to) ? (interpolation_value = to) : (interpolation_value = from);
- rv = lwpoint_interpolate(q, p, r, dims, ordinate, interpolation_value);
+ rv = lwpoint_interpolate(q, p, r, hasz, hasm, ordinate, interpolation_value);
rv = ptarray_append_point(dp, r, LW_FALSE);
LWDEBUGF(4, " [1] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
}
{
double interpolation_value;
(ordinate_value_p > to) ? (interpolation_value = to) : (interpolation_value = from);
- rv = lwpoint_interpolate(q, p, r, dims, ordinate, interpolation_value);
+ rv = lwpoint_interpolate(q, p, r, hasz, hasm, ordinate, interpolation_value);
rv = ptarray_append_point(dp, r, LW_FALSE);
LWDEBUGF(4, " [2] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
}
* so we need to add *two* interpolated points! */
dp = ptarray_construct(hasz, hasm, 2);
/* Interpolate lower point. */
- rv = lwpoint_interpolate(p, q, r, dims, ordinate, from);
+ rv = lwpoint_interpolate(p, q, r, hasz, hasm, ordinate, from);
ptarray_set_point4d(dp, 0, r);
/* Interpolate upper point. */
- rv = lwpoint_interpolate(p, q, r, dims, ordinate, to);
+ rv = lwpoint_interpolate(p, q, r, hasz, hasm, ordinate, to);
ptarray_set_point4d(dp, 1, r);
}
else if ( i && ordinate_value_q > to && ordinate_value_p < from )
* so we need to add *two* interpolated points! */
dp = ptarray_construct(hasz, hasm, 2);
/* Interpolate upper point. */
- rv = lwpoint_interpolate(p, q, r, dims, ordinate, to);
+ rv = lwpoint_interpolate(p, q, r, hasz, hasm, ordinate, to);
ptarray_set_point4d(dp, 0, r);
/* Interpolate lower point. */
- rv = lwpoint_interpolate(p, q, r, dims, ordinate, from);
+ rv = lwpoint_interpolate(p, q, r, hasz, hasm, ordinate, from);
ptarray_set_point4d(dp, 1, r);
}
/* We have an extant point-array, save it out to a multi-line. */
return NULL;
-}
\ No newline at end of file
+}
+
+LWCOLLECTION*
+lwgeom_clip_to_ordinate_range(const LWGEOM *lwin, char ordinate, double from, double to)
+{
+ if ( ! lwin )
+ lwerror("lwgeom_clip_to_ordinate_range: null input geometry!");
+
+ switch ( lwin->type )
+ {
+ case LINETYPE:
+ return lwline_clip_to_ordinate_range((LWLINE*)lwin, ordinate, from, to);
+ case MULTILINETYPE:
+ return lwmline_clip_to_ordinate_range((LWMLINE*)lwin, ordinate, from, to);
+ default:
+ lwerror("This function only accepts LINESTRING or MULTILINESTRING as arguments.");
+ }
+
+ return NULL;
+}
/* Prototypes */
Datum LWGEOM_simplify2d(PG_FUNCTION_ARGS);
Datum ST_LineCrossingDirection(PG_FUNCTION_ARGS);
-Datum ST_LocateBetweenElevations(PG_FUNCTION_ARGS);
double determineSide(POINT2D *seg1, POINT2D *seg2, POINT2D *point);
int isOnSegment(POINT2D *seg1, POINT2D *seg2, POINT2D *point);
}
-PG_FUNCTION_INFO_V1(ST_LocateBetweenElevations);
-Datum ST_LocateBetweenElevations(PG_FUNCTION_ARGS)
-{
- GSERIALIZED *geom_in = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
- double from = PG_GETARG_FLOAT8(1);
- double to = PG_GETARG_FLOAT8(2);
- LWCOLLECTION *geom_out = NULL;
- LWGEOM *line_in = NULL;
- char geomtype = gserialized_get_type(geom_in);
- static int ordinate = 2; /* Z */
-
- if ( ! ( geomtype == LINETYPE || geomtype == MULTILINETYPE ) )
- {
- elog(ERROR,"This function only accepts LINESTRING or MULTILINESTRING as arguments.");
- PG_RETURN_NULL();
- }
-
- line_in = lwgeom_from_gserialized(geom_in);
-
- if ( ! FLAGS_GET_Z(line_in->flags) )
- {
- elog(ERROR,"This function only accepts LINESTRING or MULTILINESTRING with Z values as arguments.");
- PG_RETURN_NULL();
- }
-
- if ( geomtype == LINETYPE )
- {
- geom_out = lwline_clip_to_ordinate_range((LWLINE*)line_in, ordinate, from, to);
- }
- else if ( geomtype == MULTILINETYPE )
- {
- geom_out = lwmline_clip_to_ordinate_range((LWMLINE*)line_in, ordinate, from, to);
- }
- lwgeom_free(line_in);
- if ( ! geom_out )
- {
- elog(ERROR,"The lwline_clip_to_ordinate_range returned null.");
- PG_RETURN_NULL();
- }
-
- PG_FREE_IF_COPY(geom_in, 0);
- PG_RETURN_POINTER(geometry_serialize((LWGEOM*)geom_out));
-}
/***********************************************************************
* --strk@keybit.net
PG_FUNCTION_INFO_V1(LWGEOM_collect);
Datum LWGEOM_collect(PG_FUNCTION_ARGS)
{
- GSERIALIZED *pglwgeom1, *pglwgeom2, *result;
+ GSERIALIZED *gser1, *gser2, *result;
LWGEOM *lwgeoms[2], *outlwg;
uint32 type1, type2;
uint8_t outtype;
if (PG_ARGISNULL(1))
PG_RETURN_DATUM(PG_GETARG_DATUM(0));
- pglwgeom1 = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
- pglwgeom2 = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+ gser1 = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+ gser2 = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
- POSTGIS_DEBUGF(3, "LWGEOM_collect(%s, %s): call", lwtype_name(gserialized_get_type(pglwgeom1)), lwtype_name(gserialized_get_type(pglwgeom2)));
+ POSTGIS_DEBUGF(3, "LWGEOM_collect(%s, %s): call", lwtype_name(gserialized_get_type(gser1)), lwtype_name(gserialized_get_type(gser2)));
- if ( FLAGS_GET_ZM(pglwgeom1->flags) != FLAGS_GET_ZM(pglwgeom2->flags) )
+ if ( FLAGS_GET_ZM(gser1->flags) != FLAGS_GET_ZM(gser2->flags) )
{
elog(ERROR,"Cannot ST_Collect geometries with differing dimensionality.");
PG_RETURN_NULL();
}
- srid = gserialized_get_srid(pglwgeom1);
- error_if_srid_mismatch(srid, gserialized_get_srid(pglwgeom2));
+ srid = gserialized_get_srid(gser1);
+ error_if_srid_mismatch(srid, gserialized_get_srid(gser2));
- lwgeoms[0] = lwgeom_from_gserialized(pglwgeom1);
- lwgeoms[1] = lwgeom_from_gserialized(pglwgeom2);
+ lwgeoms[0] = lwgeom_from_gserialized(gser1);
+ lwgeoms[1] = lwgeom_from_gserialized(gser2);
type1 = lwgeoms[0]->type;
type2 = lwgeoms[1]->type;
lwgeom_free(lwgeoms[0]);
lwgeom_free(lwgeoms[1]);
- PG_FREE_IF_COPY(pglwgeom1, 0);
- PG_FREE_IF_COPY(pglwgeom2, 1);
+ PG_FREE_IF_COPY(gser1, 0);
+ PG_FREE_IF_COPY(gser2, 1);
PG_RETURN_POINTER(result);
}
gbox_expand(&gbox, d);
- pa = ptarray_construct_empty(FLAGS_GET_Z(lwgeom->flags), FLAGS_GET_M(lwgeom->flags), 5);
+ pa = ptarray_construct_empty(lwgeom_has_z(lwgeom), lwgeom_has_m(lwgeom), 5);
/* Assign coordinates to POINT2D array */
pt.x = gbox.xmin;
PG_RETURN_POINTER(gout);
}
+
+/*
+* Locate the portion of a line between the specified measures
+*/
+Datum ST_LocateBetween(PG_FUNCTION_ARGS);
+PG_FUNCTION_INFO_V1(ST_LocateBetween);
+Datum ST_LocateBetween(PG_FUNCTION_ARGS)
+{
+ GSERIALIZED *geom_in = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+ double from = PG_GETARG_FLOAT8(1);
+ double to = PG_GETARG_FLOAT8(2);
+ double offset = PG_GETARG_FLOAT8(3);
+ LWCOLLECTION *geom_out = NULL;
+ LWGEOM *line_in = NULL;
+ static char ordinate = 'M'; /* M */
+
+ if ( ! gserialized_has_m(geom_in) )
+ {
+ elog(ERROR,"This function only accepts geometries that have an M dimension.");
+ PG_RETURN_NULL();
+ }
+
+ line_in = lwgeom_from_gserialized(geom_in);
+ geom_out = lwgeom_clip_to_ordinate_range(line_in, ordinate, from, to);
+ lwgeom_free(line_in);
+ PG_FREE_IF_COPY(geom_in, 0);
+
+ if ( ! geom_out )
+ {
+ elog(ERROR,"lwline_clip_to_ordinate_range returned null");
+ PG_RETURN_NULL();
+ }
+
+ PG_RETURN_POINTER(geometry_serialize((LWGEOM*)geom_out));
+}
+
+/*
+* Locate the portion of a line between the specified elevations
+*/
+Datum ST_LocateBetweenElevations(PG_FUNCTION_ARGS);
+PG_FUNCTION_INFO_V1(ST_LocateBetweenElevations);
+Datum ST_LocateBetweenElevations(PG_FUNCTION_ARGS)
+{
+ GSERIALIZED *geom_in = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+ double from = PG_GETARG_FLOAT8(1);
+ double to = PG_GETARG_FLOAT8(2);
+ LWCOLLECTION *geom_out = NULL;
+ LWGEOM *line_in = NULL;
+ static char ordinate = 'Z'; /* Z */
+
+ if ( ! gserialized_has_z(geom_in) )
+ {
+ elog(ERROR,"This function only accepts LINESTRING or MULTILINESTRING with Z dimensions.");
+ PG_RETURN_NULL();
+ }
+
+ line_in = lwgeom_from_gserialized(geom_in);
+ geom_out = lwgeom_clip_to_ordinate_range(line_in, ordinate, from, to);
+ lwgeom_free(line_in);
+ PG_FREE_IF_COPY(geom_in, 0);
+
+ if ( ! geom_out )
+ {
+ elog(ERROR,"lwline_clip_to_ordinate_range returned null");
+ PG_RETURN_NULL();
+ }
+
+ PG_RETURN_POINTER(geometry_serialize((LWGEOM*)geom_out));
+}
\ No newline at end of file
$$ SELECT CASE WHEN NOT $1 && $2 THEN 0 ELSE _ST_LineCrossingDirection($1,$2) END $$\r
LANGUAGE 'sql' IMMUTABLE;\r
\r
-\r
--- Only accepts LINESTRING as parameters.\r
--- Availability: 1.4.0\r
-CREATE OR REPLACE FUNCTION ST_LocateBetweenElevations(geometry, float8, float8)\r
- RETURNS geometry\r
- AS 'MODULE_PATHNAME', 'ST_LocateBetweenElevations'\r
- LANGUAGE 'C' IMMUTABLE STRICT;\r
-\r
-- Requires GEOS >= 3.0.0\r
-- Availability: 1.3.3\r
CREATE OR REPLACE FUNCTION ST_SimplifyPreserveTopology(geometry, float8)\r
-- SQL-MM\r
---------------------------------------------------------------\r
-- PostGIS equivalent function: ST_ndims(geometry)\r
-CREATE OR REPLACE FUNCTION ST_CoordDim(geometry)\r
+CREATE OR REPLACE FUNCTION ST_CoordDim(Geometry geometry)\r
RETURNS smallint\r
AS 'MODULE_PATHNAME', 'LWGEOM_ndims'\r
LANGUAGE 'C' IMMUTABLE STRICT; \r
RETURNS geometry AS 'SELECT ST_CurveToLine($1, 32)'\r
LANGUAGE 'SQL' IMMUTABLE STRICT;\r
\r
-CREATE OR REPLACE FUNCTION ST_HasArc(geometry)\r
+CREATE OR REPLACE FUNCTION ST_HasArc(Geometry geometry)\r
RETURNS boolean\r
AS 'MODULE_PATHNAME', 'LWGEOM_has_arc'\r
LANGUAGE 'C' IMMUTABLE STRICT;\r
\r
-CREATE OR REPLACE FUNCTION ST_LineToCurve(geometry)\r
+CREATE OR REPLACE FUNCTION ST_LineToCurve(Geometry geometry)\r
RETURNS geometry\r
AS 'MODULE_PATHNAME', 'LWGEOM_line_desegmentize'\r
LANGUAGE 'C' IMMUTABLE STRICT;\r
\r
-- Availability: 1.5.0\r
-CREATE OR REPLACE FUNCTION _ST_OrderingEquals(geometry, geometry)\r
+CREATE OR REPLACE FUNCTION _ST_OrderingEquals(GeometryA geometry, GeometryB geometry)\r
RETURNS boolean\r
AS 'MODULE_PATHNAME', 'LWGEOM_same'\r
LANGUAGE 'C' IMMUTABLE STRICT\r
COST 100;\r
\r
-- Availability: 1.3.0\r
-CREATE OR REPLACE FUNCTION ST_OrderingEquals(geometry, geometry)\r
+CREATE OR REPLACE FUNCTION ST_OrderingEquals(GeometryA geometry, GeometryB geometry)\r
RETURNS boolean\r
AS $$ \r
SELECT $1 ~= $2 AND _ST_OrderingEquals($1, $2)\r
-- SQL/MM - SQL Functions on type ST_Point\r
-------------------------------------------------------------------------------\r
\r
--- PostGIS equivalent function: ST_MakePoint(float8,float8)\r
+-- PostGIS equivalent function: ST_MakePoint(XCoordinate float8,YCoordinate float8)\r
CREATE OR REPLACE FUNCTION ST_Point(float8, float8)\r
RETURNS geometry\r
AS 'MODULE_PATHNAME', 'LWGEOM_makepoint'\r
LANGUAGE 'C' IMMUTABLE STRICT; \r
\r
--- PostGIS equivalent function: ST_MakePolygon(geometry)\r
+-- PostGIS equivalent function: ST_MakePolygon(Geometry geometry)\r
CREATE OR REPLACE FUNCTION ST_Polygon(geometry, int)\r
RETURNS geometry\r
AS $$ \r
$$ \r
LANGUAGE 'SQL' IMMUTABLE STRICT; \r
\r
--- PostGIS equivalent function: GeomFromWKB(bytea))\r
+-- PostGIS equivalent function: GeomFromWKB(WKB bytea))\r
-- Note: Defaults to an SRID=-1, not 0 as per SQL/MM specs.\r
-\r
-CREATE OR REPLACE FUNCTION ST_WKBToSQL(bytea)\r
+CREATE OR REPLACE FUNCTION ST_WKBToSQL(WKB bytea)\r
RETURNS geometry\r
AS 'MODULE_PATHNAME','LWGEOM_from_WKB'\r
LANGUAGE 'C' IMMUTABLE STRICT; \r
---\r
-- Linear referencing functions\r
---\r
-CREATE OR REPLACE FUNCTION ST_LocateBetween(Geometry geometry, Measure1 float8, Measure2 float8, Offsets float8 default 0.0)\r
+-- Availability: 2.0.0\r
+CREATE OR REPLACE FUNCTION ST_LocateBetween(Geometry geometry, FromMeasure float8, ToMeasure float8, LeftRightOffset float8 default 0.0)\r
RETURNS geometry\r
- AS 'MODULE_PATHNAME', 'LWGEOM_locate_between_m'\r
+ AS 'MODULE_PATHNAME', 'ST_LocateBetween'\r
LANGUAGE 'C' IMMUTABLE STRICT;\r
\r
-CREATE OR REPLACE FUNCTION ST_LocateAlong(Geometry geometry, Measure float8, Offsets float8 default 0.0)\r
+-- Availability: 2.0.0\r
+CREATE OR REPLACE FUNCTION ST_LocateAlong(Geometry geometry, Measure float8, LeftRightOffset float8 default 0.0)\r
RETURNS geometry\r
AS 'MODULE_PATHNAME', 'ST_LocateAlong'\r
LANGUAGE 'C' IMMUTABLE STRICT;\r
\r
+-- Only accepts LINESTRING as parameters.\r
+-- Availability: 1.4.0\r
+CREATE OR REPLACE FUNCTION ST_LocateBetweenElevations(Geometry geometry, FromElevation float8, ToElevation float8)\r
+ RETURNS geometry\r
+ AS 'MODULE_PATHNAME', 'ST_LocateBetweenElevations'\r
+ LANGUAGE 'C' IMMUTABLE STRICT;\r
+\r
+\r
\r
---------------------------------------------------------------\r
-- END\r