PostGIS  2.5.0dev-r@@SVN_REVISION@@
Datum LWGEOM_line_substring ( PG_FUNCTION_ARGS  )

Definition at line 430 of file lwgeom_functions_analytic.c.

References COLLECTIONTYPE, dumpnode::geom, geometry_serialize(), LWMLINE::geoms, gserialized_get_type(), if(), LINETYPE, LW_FALSE, LW_TRUE, lwalloc(), lwcollection_construct(), lwgeom_as_lwline(), lwgeom_as_lwmline(), lwgeom_free(), lwgeom_from_gserialized(), lwgeom_is_empty(), lwline_construct(), lwline_release(), lwmline_release(), lwpoint_construct(), MULTILINETYPE, LWMLINE::ngeoms, POINTARRAY::npoints, LWLINE::points, ptarray_length_2d(), ptarray_substring(), LWLINE::srid, LWMLINE::srid, and SRID_UNKNOWN.

431 {
432  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
433  double from = PG_GETARG_FLOAT8(1);
434  double to = PG_GETARG_FLOAT8(2);
435  LWGEOM *olwgeom;
436  POINTARRAY *ipa, *opa;
437  GSERIALIZED *ret;
438  int type = gserialized_get_type(geom);
439 
440  if ( from < 0 || from > 1 )
441  {
442  elog(ERROR,"line_interpolate_point: 2nd arg isn't within [0,1]");
443  PG_RETURN_NULL();
444  }
445 
446  if ( to < 0 || to > 1 )
447  {
448  elog(ERROR,"line_interpolate_point: 3rd arg isn't within [0,1]");
449  PG_RETURN_NULL();
450  }
451 
452  if ( from > to )
453  {
454  elog(ERROR, "2nd arg must be smaller then 3rd arg");
455  PG_RETURN_NULL();
456  }
457 
458  if ( type == LINETYPE )
459  {
461 
462  if ( lwgeom_is_empty((LWGEOM*)iline) )
463  {
464  /* TODO return empty line */
465  lwline_release(iline);
466  PG_FREE_IF_COPY(geom, 0);
467  PG_RETURN_NULL();
468  }
469 
470  ipa = iline->points;
471 
472  opa = ptarray_substring(ipa, from, to, 0);
473 
474  if ( opa->npoints == 1 ) /* Point returned */
475  olwgeom = (LWGEOM *)lwpoint_construct(iline->srid, NULL, opa);
476  else
477  olwgeom = (LWGEOM *)lwline_construct(iline->srid, NULL, opa);
478 
479  }
480  else if ( type == MULTILINETYPE )
481  {
482  LWMLINE *iline;
483  uint32_t i = 0, g = 0;
484  int homogeneous = LW_TRUE;
485  LWGEOM **geoms = NULL;
486  double length = 0.0, sublength = 0.0, minprop = 0.0, maxprop = 0.0;
487 
489 
490  if ( lwgeom_is_empty((LWGEOM*)iline) )
491  {
492  /* TODO return empty collection */
493  lwmline_release(iline);
494  PG_FREE_IF_COPY(geom, 0);
495  PG_RETURN_NULL();
496  }
497 
498  /* Calculate the total length of the mline */
499  for ( i = 0; i < iline->ngeoms; i++ )
500  {
501  LWLINE *subline = (LWLINE*)iline->geoms[i];
502  if ( subline->points && subline->points->npoints > 1 )
503  length += ptarray_length_2d(subline->points);
504  }
505 
506  geoms = lwalloc(sizeof(LWGEOM*) * iline->ngeoms);
507 
508  /* Slice each sub-geometry of the multiline */
509  for ( i = 0; i < iline->ngeoms; i++ )
510  {
511  LWLINE *subline = (LWLINE*)iline->geoms[i];
512  double subfrom = 0.0, subto = 0.0;
513 
514  if ( subline->points && subline->points->npoints > 1 )
515  sublength += ptarray_length_2d(subline->points);
516 
517  /* Calculate proportions for this subline */
518  minprop = maxprop;
519  maxprop = sublength / length;
520 
521  /* This subline doesn't reach the lowest proportion requested
522  or is beyond the highest proporton */
523  if ( from > maxprop || to < minprop )
524  continue;
525 
526  if ( from <= minprop )
527  subfrom = 0.0;
528  if ( to >= maxprop )
529  subto = 1.0;
530 
531  if ( from > minprop && from <= maxprop )
532  subfrom = (from - minprop) / (maxprop - minprop);
533 
534  if ( to < maxprop && to >= minprop )
535  subto = (to - minprop) / (maxprop - minprop);
536 
537 
538  opa = ptarray_substring(subline->points, subfrom, subto, 0);
539  if ( opa && opa->npoints > 0 )
540  {
541  if ( opa->npoints == 1 ) /* Point returned */
542  {
543  geoms[g] = (LWGEOM *)lwpoint_construct(SRID_UNKNOWN, NULL, opa);
544  homogeneous = LW_FALSE;
545  }
546  else
547  {
548  geoms[g] = (LWGEOM *)lwline_construct(SRID_UNKNOWN, NULL, opa);
549  }
550  g++;
551  }
552 
553 
554 
555  }
556  /* If we got any points, we need to return a GEOMETRYCOLLECTION */
557  if ( ! homogeneous )
558  type = COLLECTIONTYPE;
559 
560  olwgeom = (LWGEOM*)lwcollection_construct(type, iline->srid, NULL, g, geoms);
561  }
562  else
563  {
564  elog(ERROR,"line_substring: 1st arg isn't a line");
565  PG_RETURN_NULL();
566  }
567 
568  ret = geometry_serialize(olwgeom);
569  lwgeom_free(olwgeom);
570  PG_FREE_IF_COPY(geom, 0);
571  PG_RETURN_POINTER(ret);
572 
573 }
#define LINETYPE
Definition: liblwgeom.h:85
uint32_t gserialized_get_type(const GSERIALIZED *s)
Extract the geometry type from the serialized form (it hides in the anonymous data area...
Definition: g_serialized.c:86
LWCOLLECTION * lwcollection_construct(uint8_t type, int srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms)
Definition: lwcollection.c:43
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1137
POINTARRAY * ptarray_substring(POINTARRAY *pa, double d1, double d2, double tolerance)
start location (distance from start / total distance) end location (distance from start / total dist...
Definition: ptarray.c:1053
double ptarray_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY (even if it's 3d)
Definition: ptarray.c:1682
int32_t srid
Definition: liblwgeom.h:420
unsigned int uint32_t
Definition: uthash.h:78
LWGEOM * geom
#define LW_FALSE
Definition: liblwgeom.h:76
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:75
LWLINE * lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:42
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:187
LWMLINE * lwgeom_as_lwmline(const LWGEOM *lwgeom)
Definition: lwgeom.c:241
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:169
uint32_t ngeoms
Definition: liblwgeom.h:480
LWLINE ** geoms
Definition: liblwgeom.h:482
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
LWPOINT * lwpoint_construct(int srid, GBOX *bbox, POINTARRAY *point)
Definition: lwpoint.c:129
void * lwalloc(size_t size)
Definition: lwutil.c:229
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members) ...
Definition: lwgeom.c:1386
void lwmline_release(LWMLINE *lwline)
Definition: lwmline.c:32
#define MULTILINETYPE
Definition: liblwgeom.h:88
void lwline_release(LWLINE *lwline)
Definition: lwline.c:134
if(!(yy_init))
Definition: lwin_wkt_lex.c:888
#define COLLECTIONTYPE
Definition: liblwgeom.h:90
int32_t srid
Definition: liblwgeom.h:479
POINTARRAY * points
Definition: liblwgeom.h:421
uint32_t npoints
Definition: liblwgeom.h:370

Here is the call graph for this function: