#include "math.h"
#define DEBUG 0
-#define DEBUG_INERPOLATION 0
+#define DEBUG_INTERPOLATION 0
Datum LWGEOM_locate_between_m(PG_FUNCTION_ARGS);
else ret |= 0x0010;
}
+ /*
+ * if m0 and m1 have the same value
+ * avoid computation of second point to
+ * reduce rouding problems with floating
+ * numbers.
+ *
+ * The two points must be equal anyway.
+ */
+ if ( m0 == m1 )
+ {
+ memcpy(p2, p1, sizeof(POINT4D));
+ if ( swapped ) ret |= 0x0010;
+ else ret |= 0x0100;
+ return ret;
+ }
+
/*
* Second point out of range, project
* it on the range
/*
* Line is assumed to have an M value.
+ *
* Return NULL if no parts of the line are in the given range (inclusive)
+ *
* Return an LWCOLLECTION with LWLINES and LWPOINT being consecutive
* and isolated points on the line falling in the range.
- * Points are interpolated.
+ *
+ * X,Y and Z (if present) ordinates are interpolated.
+ *
*/
static LWGEOM *
lwline_locate_between_m(LWLINE *lwline_in, double m0, double m1)
int i;
LWGEOM **geoms;
int ngeoms;
+ int outtype;
+ int typeflag=0; /* see flags below */
+ const int pointflag=0x01;
+ const int lineflag=0x10;
#if DEBUG
lwnotice("lwline_locate_between called for lwline %x", lwline_in);
lwpoint->bbox=NULL;
lwpoint->point=pa;
geoms[i]=(LWGEOM *)lwpoint;
+ typeflag|=pointflag;
}
/* This is a line */
lwline->bbox=NULL;
lwline->points=pa;
geoms[i]=(LWGEOM *)lwline;
+ typeflag|=lineflag;
}
/* This is a bug */
}
- return (LWGEOM *)lwcollection_construct(COLLECTIONTYPE,
- lwline_in->SRID, NULL, ngeoms, geoms);
+ if ( ngeoms == 1 )
+ {
+ return geoms[0];
+ }
+ else
+ {
+ /* Choose best type */
+ if ( typeflag == 1 ) outtype=MULTIPOINTTYPE;
+ else if ( typeflag == 2 ) outtype=MULTILINETYPE;
+ else outtype = COLLECTIONTYPE;
+
+ return (LWGEOM *)lwcollection_construct(outtype,
+ lwline_in->SRID, NULL, ngeoms, geoms);
+ }
}
/*
/* Polygon types are not supported */
case POLYGONTYPE:
case MULTIPOLYGONTYPE:
+ lwerror("Areal geometries are not supported by locate_between_measures");
return NULL;
}
*
* Implements SQL/MM ST_LocateBetween(measure, measure) method.
* See ISO/IEC CD 13249-3:200x(E)
+ *
*/
PG_FUNCTION_INFO_V1(LWGEOM_locate_between_m);
Datum LWGEOM_locate_between_m(PG_FUNCTION_ARGS)
}
/*
- * Return NULL if input is a polygon, a multipolygon or a collection
+ * Raise an error if input is a polygon, a multipolygon
+ * or a collection
*/
type=lwgeom_getType(gin->type);
if ( type == POLYGONTYPE || type == MULTIPOLYGONTYPE || type == COLLECTIONTYPE )
{
+ lwerror("Areal or Collection types are not supported");
PG_RETURN_NULL();
}
select 'LINEZM_3', asewkt(locate_between_measures('LINESTRING(0 10 100 0, 0 0 0 10, 10 0 0 0)', 2, 18));
select 'LINEZM_4', asewkt(locate_between_measures('LINESTRING(0 10 100 0, 0 0 0 20, 10 0 0 0)', 2, 18));
select 'LINEZM_5', asewkt(locate_between_measures('LINESTRING(0 10 100 0, 0 0 0 20, 0 10 10 40, 10 0 0 0)', 2, 18));
-
+select 'LINEZM_6', asewkt(locate_between_measures('LINESTRING(0 10 10 40, 10 0 0 0)', 2, 2));
MPNT_2|GEOMETRYCOLLECTIONM(POINT(2 2 5))
MPNT_3|GEOMETRYCOLLECTIONM EMPTY
MPNT_4|GEOMETRYCOLLECTIONM(POINT(1 2 8),POINT(2 2 5))
-LINEZM_1|GEOMETRYCOLLECTION(LINESTRING(0 8 80 2,0 0 0 10))
-LINEZM_2|GEOMETRYCOLLECTION(LINESTRING(0 8 20 2,0 0 100 10))
-LINEZM_3|GEOMETRYCOLLECTION(LINESTRING(0 8 80 2,0 0 0 10,8 0 0 2))
+LINEZM_1|LINESTRING(0 8 80 2,0 0 0 10)
+LINEZM_2|LINESTRING(0 8 20 2,0 0 100 10)
+LINEZM_3|LINESTRING(0 8 80 2,0 0 0 10,8 0 0 2)
LINEZM_4|GEOMETRYCOLLECTION(LINESTRING(0 9 90 2,0 1 10 18),LINESTRING(1 0 0 18,9 0 0 2))
LINEZM_5|GEOMETRYCOLLECTION(LINESTRING(0 9 90 2,0 1 10 18),LINESTRING(5.5 4.5 4.5 18,9.5 0.5 0.5 2))
+LINEZM_6|POINT(9.5 0.5 0.5 2)