PostGIS  2.2.8dev-r@@SVN_REVISION@@

◆ LWGEOM_line_substring()

Datum LWGEOM_line_substring ( PG_FUNCTION_ARGS  )

Definition at line 471 of file lwgeom_functions_analytic.c.

References COLLECTIONTYPE, dumpnode::geom, geometry_serialize(), 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, POINTARRAY::npoints, LWLINE::points, ptarray_length_2d(), ptarray_substring(), LWGEOM::srid, SRID_UNKNOWN, and ovdump::type.

Referenced by ST_LineCrossingDirection().

472 {
473  GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
474  double from = PG_GETARG_FLOAT8(1);
475  double to = PG_GETARG_FLOAT8(2);
476  LWGEOM *olwgeom;
477  POINTARRAY *ipa, *opa;
478  GSERIALIZED *ret;
479  int type = gserialized_get_type(geom);
480 
481  if ( from < 0 || from > 1 )
482  {
483  elog(ERROR,"line_interpolate_point: 2nd arg isn't within [0,1]");
484  PG_RETURN_NULL();
485  }
486 
487  if ( to < 0 || to > 1 )
488  {
489  elog(ERROR,"line_interpolate_point: 3rd arg isn't within [0,1]");
490  PG_RETURN_NULL();
491  }
492 
493  if ( from > to )
494  {
495  elog(ERROR, "2nd arg must be smaller then 3rd arg");
496  PG_RETURN_NULL();
497  }
498 
499  if ( type == LINETYPE )
500  {
502 
503  if ( lwgeom_is_empty((LWGEOM*)iline) )
504  {
505  /* TODO return empty line */
506  lwline_release(iline);
507  PG_FREE_IF_COPY(geom, 0);
508  PG_RETURN_NULL();
509  }
510 
511  ipa = iline->points;
512 
513  opa = ptarray_substring(ipa, from, to, 0);
514 
515  if ( opa->npoints == 1 ) /* Point returned */
516  olwgeom = (LWGEOM *)lwpoint_construct(iline->srid, NULL, opa);
517  else
518  olwgeom = (LWGEOM *)lwline_construct(iline->srid, NULL, opa);
519 
520  }
521  else if ( type == MULTILINETYPE )
522  {
523  LWMLINE *iline;
524  int i = 0, g = 0;
525  int homogeneous = LW_TRUE;
526  LWGEOM **geoms = NULL;
527  double length = 0.0, sublength = 0.0, minprop = 0.0, maxprop = 0.0;
528 
530 
531  if ( lwgeom_is_empty((LWGEOM*)iline) )
532  {
533  /* TODO return empty collection */
534  lwmline_release(iline);
535  PG_FREE_IF_COPY(geom, 0);
536  PG_RETURN_NULL();
537  }
538 
539  /* Calculate the total length of the mline */
540  for ( i = 0; i < iline->ngeoms; i++ )
541  {
542  LWLINE *subline = (LWLINE*)iline->geoms[i];
543  if ( subline->points && subline->points->npoints > 1 )
544  length += ptarray_length_2d(subline->points);
545  }
546 
547  geoms = lwalloc(sizeof(LWGEOM*) * iline->ngeoms);
548 
549  /* Slice each sub-geometry of the multiline */
550  for ( i = 0; i < iline->ngeoms; i++ )
551  {
552  LWLINE *subline = (LWLINE*)iline->geoms[i];
553  double subfrom = 0.0, subto = 0.0;
554 
555  if ( subline->points && subline->points->npoints > 1 )
556  sublength += ptarray_length_2d(subline->points);
557 
558  /* Calculate proportions for this subline */
559  minprop = maxprop;
560  maxprop = sublength / length;
561 
562  /* This subline doesn't reach the lowest proportion requested
563  or is beyond the highest proporton */
564  if ( from > maxprop || to < minprop )
565  continue;
566 
567  if ( from <= minprop )
568  subfrom = 0.0;
569  if ( to >= maxprop )
570  subto = 1.0;
571 
572  if ( from > minprop && from <= maxprop )
573  subfrom = (from - minprop) / (maxprop - minprop);
574 
575  if ( to < maxprop && to >= minprop )
576  subto = (to - minprop) / (maxprop - minprop);
577 
578 
579  opa = ptarray_substring(subline->points, subfrom, subto, 0);
580  if ( opa && opa->npoints > 0 )
581  {
582  if ( opa->npoints == 1 ) /* Point returned */
583  {
584  geoms[g] = (LWGEOM *)lwpoint_construct(SRID_UNKNOWN, NULL, opa);
585  homogeneous = LW_FALSE;
586  }
587  else
588  {
589  geoms[g] = (LWGEOM *)lwline_construct(SRID_UNKNOWN, NULL, opa);
590  }
591  g++;
592  }
593 
594 
595 
596  }
597  /* If we got any points, we need to return a GEOMETRYCOLLECTION */
598  if ( ! homogeneous )
599  type = COLLECTIONTYPE;
600 
601  olwgeom = (LWGEOM*)lwcollection_construct(type, iline->srid, NULL, g, geoms);
602  }
603  else
604  {
605  elog(ERROR,"line_substring: 1st arg isn't a line");
606  PG_RETURN_NULL();
607  }
608 
609  ret = geometry_serialize(olwgeom);
610  lwgeom_free(olwgeom);
611  PG_FREE_IF_COPY(geom, 0);
612  PG_RETURN_POINTER(ret);
613 
614 }
#define LINETYPE
Definition: liblwgeom.h:71
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:55
LWCOLLECTION * lwcollection_construct(uint8_t type, int srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms)
Definition: lwcollection.c:30
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int npoints
Definition: liblwgeom.h:355
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1050
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&#39;s 3d)
Definition: ptarray.c:1645
int32_t srid
Definition: liblwgeom.h:383
LWGEOM * geom
#define LW_FALSE
Definition: liblwgeom.h:62
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:61
LWLINE * lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:29
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:172
LWMLINE * lwgeom_as_lwmline(const LWGEOM *lwgeom)
Definition: lwgeom.c:161
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:89
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
type
Definition: ovdump.py:41
LWPOINT * lwpoint_construct(int srid, GBOX *bbox, POINTARRAY *point)
Definition: lwpoint.c:98
void * lwalloc(size_t size)
Definition: lwutil.c:199
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:1297
void lwmline_release(LWMLINE *lwline)
Definition: lwmline.c:18
#define MULTILINETYPE
Definition: liblwgeom.h:74
void lwline_release(LWLINE *lwline)
Definition: lwline.c:121
if(!(yy_init))
#define COLLECTIONTYPE
Definition: liblwgeom.h:76
POINTARRAY * points
Definition: liblwgeom.h:406
Here is the call graph for this function:
Here is the caller graph for this function: