Ticket #390: addmeasure.patch
| File addmeasure.patch, 3.4 KB (added by pramsey, 2 years ago) |
|---|
-
liblwgeom/lwline.c
524 524 { 525 525 setPoint4d(line->points, index, newpoint); 526 526 } 527 528 /** 529 * Re-write the measure ordinate (or add one, if it isn't already there) interpolating 530 * the measure between the supplied start and end values. 531 */ 532 LWLINE* 533 lwline_measured_from_lwline(const LWLINE *lwline, double m_start, double m_end) 534 { 535 int i = 0; 536 int hasm = 0, hasz = 0; 537 int npoints = 0; 538 double length = 0.0; 539 double length_so_far = 0.0; 540 double m_range = m_end - m_start; 541 double m; 542 POINTARRAY *pa = NULL; 543 POINT3DZ p1, p2; 544 545 if( TYPE_GETTYPE(lwline->type) != LINETYPE ) 546 { 547 lwerror("lwmline_construct_from_lwline: only line types supported"); 548 return NULL; 549 } 550 551 hasz = TYPE_HASZ(lwline->type); 552 hasm = 1; 553 554 /* Null points or npoints == 0 will result in empty return geometry */ 555 if( lwline->points ) 556 { 557 npoints = lwline->points->npoints; 558 length = lwgeom_pointarray_length2d(lwline->points); 559 getPoint3dz_p(lwline->points, 0, &p1); 560 } 561 562 pa = ptarray_construct(hasz, hasm, npoints); 563 564 for( i = 0; i < npoints; i++ ) 565 { 566 POINT4D q; 567 getPoint3dz_p(lwline->points, i, &p2); 568 length_so_far += distance2d_pt_pt((POINT2D*)&p1, (POINT2D*)&p2); 569 if ( length > 0.0 ) 570 m = m_start + m_range * length_so_far / length; 571 else 572 m = 0.0; 573 q.x = p2.x; 574 q.y = p2.y; 575 q.z = p2.z; 576 q.m = m; 577 setPoint4d(pa, i, &q); 578 p1 = p2; 579 } 580 581 return lwline_construct(lwline->SRID, NULL, pa); 582 } -
liblwgeom/liblwgeom.h
1379 1379 extern POINTARRAY *ptarray_substring(POINTARRAY *, double, double); 1380 1380 extern double ptarray_locate_point(POINTARRAY *, POINT2D *); 1381 1381 extern void closest_point_on_segment(POINT2D *p, POINT2D *A, POINT2D *B, POINT2D *ret); 1382 extern LWLINE *lwline_measured_from_lwline(const LWLINE *lwline, double m_start, double m_end); 1382 1383 1383 1384 /* 1384 1385 * Ensure every segment is at most 'dist' long. -
postgis/lwgeom_functions_lrs.c
18 18 19 19 20 20 Datum LWGEOM_locate_between_m(PG_FUNCTION_ARGS); 21 Datum ST_AddMeasure(PG_FUNCTION_ARGS); 21 22 22 23 typedef struct 23 24 { … … 535 536 PG_RETURN_POINTER(gout); 536 537 } 537 538 539 540 /* 541 * CREATE OR REPLACE FUNCTION ST_AddMeasure(geometry, float8, float8) 542 * RETURNS geometry 543 * AS '$libdir/postgis-1.5', 'ST_AddMeasure' 544 * LANGUAGE 'C' IMMUTABLE STRICT; 545 */ 546 PG_FUNCTION_INFO_V1(ST_AddMeasure); 547 Datum ST_AddMeasure(PG_FUNCTION_ARGS) 548 { 549 PG_LWGEOM *gin = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); 550 PG_LWGEOM *gout; 551 double start_measure = PG_GETARG_FLOAT8(1); 552 double end_measure = PG_GETARG_FLOAT8(2); 553 LWGEOM *lwin, *lwout; 554 555 /* Raise an error if input is not a linestring */ 556 if ( TYPE_GETTYPE(gin->type) != LINETYPE ) 557 { 558 lwerror("Only LINESTRING is supported"); 559 PG_RETURN_NULL(); 560 } 561 562 lwin = pglwgeom_deserialize(gin); 563 lwout = (LWGEOM*)lwline_measured_from_lwline((LWLINE*)lwin, start_measure, end_measure); 564 lwgeom_release(lwin); 565 566 if ( lwout == NULL ) 567 PG_RETURN_NULL(); 568 569 gout = pglwgeom_serialize(lwout); 570 lwgeom_release(lwout); 571 572 PG_RETURN_POINTER(gout); 573 } 574
