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

Definition at line 493 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.

494 {
495  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
496  double from = PG_GETARG_FLOAT8(1);
497  double to = PG_GETARG_FLOAT8(2);
498  LWGEOM *olwgeom;
499  POINTARRAY *ipa, *opa;
500  GSERIALIZED *ret;
501  int type = gserialized_get_type(geom);
502 
503  if ( from < 0 || from > 1 )
504  {
505  elog(ERROR,"line_interpolate_point: 2nd arg isn't within [0,1]");
506  PG_RETURN_NULL();
507  }
508 
509  if ( to < 0 || to > 1 )
510  {
511  elog(ERROR,"line_interpolate_point: 3rd arg isn't within [0,1]");
512  PG_RETURN_NULL();
513  }
514 
515  if ( from > to )
516  {
517  elog(ERROR, "2nd arg must be smaller then 3rd arg");
518  PG_RETURN_NULL();
519  }
520 
521  if ( type == LINETYPE )
522  {
524 
525  if ( lwgeom_is_empty((LWGEOM*)iline) )
526  {
527  /* TODO return empty line */
528  lwline_release(iline);
529  PG_FREE_IF_COPY(geom, 0);
530  PG_RETURN_NULL();
531  }
532 
533  ipa = iline->points;
534 
535  opa = ptarray_substring(ipa, from, to, 0);
536 
537  if ( opa->npoints == 1 ) /* Point returned */
538  olwgeom = (LWGEOM *)lwpoint_construct(iline->srid, NULL, opa);
539  else
540  olwgeom = (LWGEOM *)lwline_construct(iline->srid, NULL, opa);
541 
542  }
543  else if ( type == MULTILINETYPE )
544  {
545  LWMLINE *iline;
546  int i = 0, g = 0;
547  int homogeneous = LW_TRUE;
548  LWGEOM **geoms = NULL;
549  double length = 0.0, sublength = 0.0, minprop = 0.0, maxprop = 0.0;
550 
552 
553  if ( lwgeom_is_empty((LWGEOM*)iline) )
554  {
555  /* TODO return empty collection */
556  lwmline_release(iline);
557  PG_FREE_IF_COPY(geom, 0);
558  PG_RETURN_NULL();
559  }
560 
561  /* Calculate the total length of the mline */
562  for ( i = 0; i < iline->ngeoms; i++ )
563  {
564  LWLINE *subline = (LWLINE*)iline->geoms[i];
565  if ( subline->points && subline->points->npoints > 1 )
566  length += ptarray_length_2d(subline->points);
567  }
568 
569  geoms = lwalloc(sizeof(LWGEOM*) * iline->ngeoms);
570 
571  /* Slice each sub-geometry of the multiline */
572  for ( i = 0; i < iline->ngeoms; i++ )
573  {
574  LWLINE *subline = (LWLINE*)iline->geoms[i];
575  double subfrom = 0.0, subto = 0.0;
576 
577  if ( subline->points && subline->points->npoints > 1 )
578  sublength += ptarray_length_2d(subline->points);
579 
580  /* Calculate proportions for this subline */
581  minprop = maxprop;
582  maxprop = sublength / length;
583 
584  /* This subline doesn't reach the lowest proportion requested
585  or is beyond the highest proporton */
586  if ( from > maxprop || to < minprop )
587  continue;
588 
589  if ( from <= minprop )
590  subfrom = 0.0;
591  if ( to >= maxprop )
592  subto = 1.0;
593 
594  if ( from > minprop && from <= maxprop )
595  subfrom = (from - minprop) / (maxprop - minprop);
596 
597  if ( to < maxprop && to >= minprop )
598  subto = (to - minprop) / (maxprop - minprop);
599 
600 
601  opa = ptarray_substring(subline->points, subfrom, subto, 0);
602  if ( opa && opa->npoints > 0 )
603  {
604  if ( opa->npoints == 1 ) /* Point returned */
605  {
606  geoms[g] = (LWGEOM *)lwpoint_construct(SRID_UNKNOWN, NULL, opa);
607  homogeneous = LW_FALSE;
608  }
609  else
610  {
611  geoms[g] = (LWGEOM *)lwline_construct(SRID_UNKNOWN, NULL, opa);
612  }
613  g++;
614  }
615 
616 
617 
618  }
619  /* If we got any points, we need to return a GEOMETRYCOLLECTION */
620  if ( ! homogeneous )
621  type = COLLECTIONTYPE;
622 
623  olwgeom = (LWGEOM*)lwcollection_construct(type, iline->srid, NULL, g, geoms);
624  }
625  else
626  {
627  elog(ERROR,"line_substring: 1st arg isn't a line");
628  PG_RETURN_NULL();
629  }
630 
631  ret = geometry_serialize(olwgeom);
632  lwgeom_free(olwgeom);
633  PG_FREE_IF_COPY(geom, 0);
634  PG_RETURN_POINTER(ret);
635 
636 }
#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:69
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.
int npoints
Definition: liblwgeom.h:370
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1063
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:1058
double ptarray_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY (even if it's 3d)
Definition: ptarray.c:1645
int32_t srid
Definition: liblwgeom.h:420
int ngeoms
Definition: liblwgeom.h:480
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:174
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:102
LWLINE ** geoms
Definition: liblwgeom.h:482
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
LWPOINT * lwpoint_construct(int srid, GBOX *bbox, POINTARRAY *point)
Definition: lwpoint.c:111
void * lwalloc(size_t size)
Definition: lwutil.c:227
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:1310
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

Here is the call graph for this function: