PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ LWGEOM_line_substring()

Datum LWGEOM_line_substring ( PG_FUNCTION_ARGS  )

Definition at line 515 of file lwgeom_functions_analytic.c.

516{
517 GSERIALIZED *geom = PG_GETARG_GSERIALIZED_P(0);
518 double from = PG_GETARG_FLOAT8(1);
519 double to = PG_GETARG_FLOAT8(2);
520 LWGEOM *olwgeom;
521 POINTARRAY *ipa, *opa;
522 GSERIALIZED *ret;
523 int type = gserialized_get_type(geom);
524
525 if ( from < 0 || from > 1 )
526 {
527 elog(ERROR,"line_interpolate_point: 2nd arg isn't within [0,1]");
528 PG_RETURN_NULL();
529 }
530
531 if ( to < 0 || to > 1 )
532 {
533 elog(ERROR,"line_interpolate_point: 3rd arg isn't within [0,1]");
534 PG_RETURN_NULL();
535 }
536
537 if ( from > to )
538 {
539 elog(ERROR, "2nd arg must be smaller then 3rd arg");
540 PG_RETURN_NULL();
541 }
542
543 if ( type == LINETYPE )
544 {
546
547 if ( lwgeom_is_empty((LWGEOM*)iline) )
548 {
549 /* TODO return empty line */
550 lwline_release(iline);
551 PG_FREE_IF_COPY(geom, 0);
552 PG_RETURN_NULL();
553 }
554
555 ipa = iline->points;
556
557 opa = ptarray_substring(ipa, from, to, 0);
558
559 if ( opa->npoints == 1 ) /* Point returned */
560 olwgeom = (LWGEOM *)lwpoint_construct(iline->srid, NULL, opa);
561 else
562 olwgeom = (LWGEOM *)lwline_construct(iline->srid, NULL, opa);
563
564 }
565 else if ( type == MULTILINETYPE )
566 {
567 LWMLINE *iline;
568 uint32_t i = 0, g = 0;
569 int homogeneous = LW_TRUE;
570 LWGEOM **geoms = NULL;
571 double length = 0.0, sublength = 0.0, minprop = 0.0, maxprop = 0.0;
572
574
575 if ( lwgeom_is_empty((LWGEOM*)iline) )
576 {
577 /* TODO return empty collection */
578 lwmline_release(iline);
579 PG_FREE_IF_COPY(geom, 0);
580 PG_RETURN_NULL();
581 }
582
583 /* Calculate the total length of the mline */
584 for ( i = 0; i < iline->ngeoms; i++ )
585 {
586 LWLINE *subline = (LWLINE*)iline->geoms[i];
587 if ( subline->points && subline->points->npoints > 1 )
588 length += ptarray_length_2d(subline->points);
589 }
590
591 geoms = lwalloc(sizeof(LWGEOM*) * iline->ngeoms);
592
593 /* Slice each sub-geometry of the multiline */
594 for ( i = 0; i < iline->ngeoms; i++ )
595 {
596 LWLINE *subline = (LWLINE*)iline->geoms[i];
597 double subfrom = 0.0, subto = 0.0;
598
599 if ( subline->points && subline->points->npoints > 1 )
600 sublength += ptarray_length_2d(subline->points);
601
602 /* Calculate proportions for this subline */
603 minprop = maxprop;
604 maxprop = sublength / length;
605
606 /* This subline doesn't reach the lowest proportion requested
607 or is beyond the highest proporton */
608 if ( from > maxprop || to < minprop )
609 continue;
610
611 if ( from <= minprop )
612 subfrom = 0.0;
613 if ( to >= maxprop )
614 subto = 1.0;
615
616 if ( from > minprop && from <= maxprop )
617 subfrom = (from - minprop) / (maxprop - minprop);
618
619 if ( to < maxprop && to >= minprop )
620 subto = (to - minprop) / (maxprop - minprop);
621
622
623 opa = ptarray_substring(subline->points, subfrom, subto, 0);
624 if ( opa && opa->npoints > 0 )
625 {
626 if ( opa->npoints == 1 ) /* Point returned */
627 {
628 geoms[g] = (LWGEOM *)lwpoint_construct(SRID_UNKNOWN, NULL, opa);
629 homogeneous = LW_FALSE;
630 }
631 else
632 {
633 geoms[g] = (LWGEOM *)lwline_construct(SRID_UNKNOWN, NULL, opa);
634 }
635 g++;
636 }
637
638
639
640 }
641 /* If we got any points, we need to return a GEOMETRYCOLLECTION */
642 if ( ! homogeneous )
644
645 olwgeom = (LWGEOM*)lwcollection_construct(type, iline->srid, NULL, g, geoms);
646 }
647 else
648 {
649 elog(ERROR,"line_substring: 1st arg isn't a line");
650 PG_RETURN_NULL();
651 }
652
653 ret = geometry_serialize(olwgeom);
654 lwgeom_free(olwgeom);
655 PG_FREE_IF_COPY(geom, 0);
656 PG_RETURN_POINTER(ret);
657
658}
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
uint32_t gserialized_get_type(const GSERIALIZED *g)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
Definition gserialized.c:89
LWCOLLECTION * lwcollection_construct(uint8_t type, int32_t srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms)
#define LW_FALSE
Definition liblwgeom.h:108
#define COLLECTIONTYPE
Definition liblwgeom.h:122
void lwgeom_free(LWGEOM *geom)
Definition lwgeom.c:1138
#define MULTILINETYPE
Definition liblwgeom.h:120
#define LINETYPE
Definition liblwgeom.h:117
POINTARRAY * ptarray_substring(POINTARRAY *pa, double d1, double d2, double tolerance)
@d1 start location (distance from start / total distance) @d2 end location (distance from start / tot...
Definition ptarray.c:1066
LWPOINT * lwpoint_construct(int32_t srid, GBOX *bbox, POINTARRAY *point)
Definition lwpoint.c:129
void lwline_release(LWLINE *lwline)
Definition lwline.c:125
double ptarray_length_2d(const POINTARRAY *pts)
Find the 2d length of the given POINTARRAY (even if it's 3d)
Definition ptarray.c:1708
void lwmline_release(LWMLINE *lwline)
Definition lwmline.c:32
void * lwalloc(size_t size)
Definition lwutil.c:227
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
Definition lwline.c:42
LWMLINE * lwgeom_as_lwmline(const LWGEOM *lwgeom)
Definition lwgeom.c:233
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition lwgeom.c:161
#define LW_TRUE
Return types for functions with status returns.
Definition liblwgeom.h:107
#define SRID_UNKNOWN
Unknown SRID value.
Definition liblwgeom.h:229
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
Definition lwinline.h:193
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
int32_t srid
Definition liblwgeom.h:446
uint32_t npoints
Definition liblwgeom.h:413

References COLLECTIONTYPE, geometry_serialize(), LWMLINE::geoms, gserialized_get_type(), 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.

Here is the call graph for this function: