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

Definition at line 701 of file lwgeom_functions_analytic.c.

References COLLECTIONTYPE, 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.

702 {
703  GSERIALIZED *geom = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
704  double from = PG_GETARG_FLOAT8(1);
705  double to = PG_GETARG_FLOAT8(2);
706  LWGEOM *olwgeom;
707  POINTARRAY *ipa, *opa;
708  GSERIALIZED *ret;
709  int type = gserialized_get_type(geom);
710 
711  if ( from < 0 || from > 1 )
712  {
713  elog(ERROR,"line_interpolate_point: 2nd arg isnt within [0,1]");
714  PG_RETURN_NULL();
715  }
716 
717  if ( to < 0 || to > 1 )
718  {
719  elog(ERROR,"line_interpolate_point: 3rd arg isnt within [0,1]");
720  PG_RETURN_NULL();
721  }
722 
723  if ( from > to )
724  {
725  elog(ERROR, "2nd arg must be smaller then 3rd arg");
726  PG_RETURN_NULL();
727  }
728 
729  if ( type == LINETYPE )
730  {
732 
733  if ( lwgeom_is_empty((LWGEOM*)iline) )
734  {
735  /* TODO return empty line */
736  lwline_release(iline);
737  PG_FREE_IF_COPY(geom, 0);
738  PG_RETURN_NULL();
739  }
740 
741  ipa = iline->points;
742 
743  opa = ptarray_substring(ipa, from, to, 0);
744 
745  if ( opa->npoints == 1 ) /* Point returned */
746  olwgeom = (LWGEOM *)lwpoint_construct(iline->srid, NULL, opa);
747  else
748  olwgeom = (LWGEOM *)lwline_construct(iline->srid, NULL, opa);
749 
750  }
751  else if ( type == MULTILINETYPE )
752  {
753  LWMLINE *iline;
754  int i = 0, g = 0;
755  int homogeneous = LW_TRUE;
756  LWGEOM **geoms = NULL;
757  double length = 0.0, sublength = 0.0, minprop = 0.0, maxprop = 0.0;
758 
760 
761  if ( lwgeom_is_empty((LWGEOM*)iline) )
762  {
763  /* TODO return empty collection */
764  lwmline_release(iline);
765  PG_FREE_IF_COPY(geom, 0);
766  PG_RETURN_NULL();
767  }
768 
769  /* Calculate the total length of the mline */
770  for ( i = 0; i < iline->ngeoms; i++ )
771  {
772  LWLINE *subline = (LWLINE*)iline->geoms[i];
773  if ( subline->points && subline->points->npoints > 1 )
774  length += ptarray_length_2d(subline->points);
775  }
776 
777  geoms = lwalloc(sizeof(LWGEOM*) * iline->ngeoms);
778 
779  /* Slice each sub-geometry of the multiline */
780  for ( i = 0; i < iline->ngeoms; i++ )
781  {
782  LWLINE *subline = (LWLINE*)iline->geoms[i];
783  double subfrom = 0.0, subto = 0.0;
784 
785  if ( subline->points && subline->points->npoints > 1 )
786  sublength += ptarray_length_2d(subline->points);
787 
788  /* Calculate proportions for this subline */
789  minprop = maxprop;
790  maxprop = sublength / length;
791 
792  /* This subline doesn't reach the lowest proportion requested
793  or is beyond the highest proporton */
794  if ( from > maxprop || to < minprop )
795  continue;
796 
797  if ( from <= minprop )
798  subfrom = 0.0;
799  if ( to >= maxprop )
800  subto = 1.0;
801 
802  if ( from > minprop && from <= maxprop )
803  subfrom = (from - minprop) / (maxprop - minprop);
804 
805  if ( to < maxprop && to >= minprop )
806  subto = (to - minprop) / (maxprop - minprop);
807 
808 
809  opa = ptarray_substring(subline->points, subfrom, subto, 0);
810  if ( opa && opa->npoints > 0 )
811  {
812  if ( opa->npoints == 1 ) /* Point returned */
813  {
814  geoms[g] = (LWGEOM *)lwpoint_construct(SRID_UNKNOWN, NULL, opa);
815  homogeneous = LW_FALSE;
816  }
817  else
818  {
819  geoms[g] = (LWGEOM *)lwline_construct(SRID_UNKNOWN, NULL, opa);
820  }
821  g++;
822  }
823 
824 
825 
826  }
827  /* If we got any points, we need to return a GEOMETRYCOLLECTION */
828  if ( ! homogeneous )
829  type = COLLECTIONTYPE;
830 
831  olwgeom = (LWGEOM*)lwcollection_construct(type, iline->srid, NULL, g, geoms);
832  }
833  else
834  {
835  elog(ERROR,"line_substring: 1st arg isnt a line");
836  PG_RETURN_NULL();
837  }
838 
839  ret = geometry_serialize(olwgeom);
840  lwgeom_free(olwgeom);
841  PG_FREE_IF_COPY(geom, 0);
842  PG_RETURN_POINTER(ret);
843 
844 }
#define LINETYPE
Definition: liblwgeom.h:61
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:56
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:327
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1006
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:1022
double ptarray_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY (even if it's 3d)
Definition: ptarray.c:1586
int32_t srid
Definition: liblwgeom.h:377
int ngeoms
Definition: liblwgeom.h:437
LWGEOM * geom
#define LW_FALSE
Definition: liblwgeom.h:52
#define LW_TRUE
Return types for functions with status returns.
Definition: liblwgeom.h:51
LWLINE * lwline_construct(int srid, GBOX *bbox, POINTARRAY *points)
Definition: lwline.c:29
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:154
LWMLINE * lwgeom_as_lwmline(const LWGEOM *lwgeom)
Definition: lwgeom.c:161
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:89
LWLINE ** geoms
Definition: liblwgeom.h:439
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
LWPOINT * lwpoint_construct(int srid, GBOX *bbox, POINTARRAY *point)
Definition: lwpoint.c:96
void * lwalloc(size_t size)
Definition: lwutil.c:175
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:1229
void lwmline_release(LWMLINE *lwline)
Definition: lwmline.c:19
#define MULTILINETYPE
Definition: liblwgeom.h:64
void lwline_release(LWLINE *lwline)
Definition: lwline.c:121
if(!(yy_init))
Definition: lwin_wkt_lex.c:860
#define COLLECTIONTYPE
Definition: liblwgeom.h:66
int32_t srid
Definition: liblwgeom.h:436
POINTARRAY * points
Definition: liblwgeom.h:378

Here is the call graph for this function: