Datum LWGEOM_line_locate_point(PG_FUNCTION_ARGS) { GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P(0); GSERIALIZED *geom2 = PG_GETARG_GSERIALIZED_P(1); LWLINE *lwline; LWPOINT *lwpoint; POINTARRAY *pa; POINT4D p, p_proj; double ret; if ( gserialized_get_type(geom1) != LINETYPE ) { elog(ERROR,"line_locate_point: 1st arg isn't a line"); PG_RETURN_NULL(); } if ( gserialized_get_type(geom2) != POINTTYPE ) { elog(ERROR,"line_locate_point: 2st arg isn't a point"); PG_RETURN_NULL(); } error_if_srid_mismatch(gserialized_get_srid(geom1), gserialized_get_srid(geom2)); lwline = lwgeom_as_lwline(lwgeom_from_gserialized(geom1)); lwpoint = lwgeom_as_lwpoint(lwgeom_from_gserialized(geom2)); pa = lwline->points; lwpoint_getPoint4d_p(lwpoint, &p); ret = ptarray_locate_point(pa, &p, NULL, &p_proj); PG_RETURN_FLOAT8(ret); }
double lwgeom_interpolate_point(const LWGEOM *lwin, const LWPOINT *lwpt) { POINT4D p, p_proj; double ret = 0.0; if ( ! lwin ) lwerror("lwgeom_interpolate_point: null input geometry!"); if ( ! lwgeom_has_m(lwin) ) lwerror("Input geometry does not have a measure dimension"); if ( lwgeom_is_empty(lwin) || lwpoint_is_empty(lwpt) ) lwerror("Input geometry is empty"); switch ( lwin->type ) { case LINETYPE: { LWLINE *lwline = lwgeom_as_lwline(lwin); lwpoint_getPoint4d_p(lwpt, &p); ret = ptarray_locate_point(lwline->points, &p, NULL, &p_proj); ret = p_proj.m; break; } default: lwerror("This function does not accept %s geometries.", lwtype_name(lwin->type)); } return ret; }
static void test_ptarray_locate_point(void) { LWLINE *line; double loc, dist; POINT4D p, l; line = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 3,20 4)")); p = getPoint4d(line->points, 0); loc = ptarray_locate_point(line->points, &p, &dist, &l); CU_ASSERT_EQUAL(loc, 0); CU_ASSERT_EQUAL(dist, 0.0); p = getPoint4d(line->points, 1); loc = ptarray_locate_point(line->points, &p, &dist, &l); CU_ASSERT_EQUAL(loc, 1); CU_ASSERT_EQUAL(dist, 0.0); p.x = 21; p.y = 4; loc = ptarray_locate_point(line->points, &p, &dist, NULL); CU_ASSERT_EQUAL(loc, 1); CU_ASSERT_EQUAL(dist, 1.0); p.x = 0; p.y = 2; loc = ptarray_locate_point(line->points, &p, &dist, &l); CU_ASSERT_EQUAL(loc, 0); CU_ASSERT_EQUAL(dist, 1.0); lwline_free(line); line = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 0,20 0,40 0)")); p.x = 20; p.y = 0; loc = ptarray_locate_point(line->points, &p, &dist, &l); CU_ASSERT_EQUAL(loc, 0.5); CU_ASSERT_EQUAL(dist, 0.0); lwline_free(line); line = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(-40 0,0 0,20 0,40 0)")); p.x = 20; p.y = 0; loc = ptarray_locate_point(line->points, &p, &dist, &l); CU_ASSERT_EQUAL(loc, 0.75); CU_ASSERT_EQUAL(dist, 0.0); lwline_free(line); line = lwgeom_as_lwline(lwgeom_from_text("LINESTRING M (0 0 0, 10 0 20)")); p.x = 5; p.y = 0; loc = ptarray_locate_point(line->points, &p, &dist, &l); CU_ASSERT_EQUAL(loc, 0.5); CU_ASSERT_EQUAL(dist, 0.0); CU_ASSERT_EQUAL(l.m, 10.0); lwline_free(line); }
Datum LWGEOM_line_locate_point(PG_FUNCTION_ARGS) { GSERIALIZED *geom1 = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); GSERIALIZED *geom2 = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); LWLINE *lwline; LWPOINT *lwpoint; POINTARRAY *pa; POINT2D p; double ret; if ( gserialized_get_type(geom1) != LINETYPE ) { elog(ERROR,"line_locate_point: 1st arg isnt a line"); PG_RETURN_NULL(); } if ( gserialized_get_type(geom2) != POINTTYPE ) { elog(ERROR,"line_locate_point: 2st arg isnt a point"); PG_RETURN_NULL(); } if ( gserialized_get_srid(geom1) != gserialized_get_srid(geom2) ) { elog(ERROR, "Operation on two geometries with different SRIDs"); PG_RETURN_NULL(); } lwline = lwgeom_as_lwline(lwgeom_from_gserialized(geom1)); lwpoint = lwgeom_as_lwpoint(lwgeom_from_gserialized(geom2)); pa = lwline->points; lwpoint_getPoint2d_p(lwpoint, &p); ret = ptarray_locate_point(pa, &p, NULL); PG_RETURN_FLOAT8(ret); }
int lwline_split_by_point_to(const LWLINE* lwline_in, const LWPOINT* blade_in, LWMLINE* v) { double loc, dist; POINT4D pt, pt_projected; POINTARRAY* pa1; POINTARRAY* pa2; double vstol; /* vertex snap tolerance */ /* Possible outcomes: * * 1. The point is not on the line or on the boundary * -> Leave collection untouched, return 0 * 2. The point is on the boundary * -> Push 1 element on the collection: * o the original line * -> Return 1 * 3. The point is in the line * -> Push 2 elements on the collection: * o start_point - cut_point * o cut_point - last_point * -> Return 2 */ getPoint4d_p(blade_in->point, 0, &pt); loc = ptarray_locate_point(lwline_in->points, &pt, &dist, &pt_projected); /* lwnotice("Location: %g -- Distance: %g", loc, dist); */ if ( dist > 0 ) /* TODO: accept a tolerance ? */ { /* No intersection */ return 0; } if ( loc == 0 || loc == 1 ) { /* Intersection is on the boundary */ return 1; } /* There is a real intersection, let's get two substrings */ /* Compute vertex snap tolerance based on line length * TODO: take as parameter ? */ vstol = ptarray_length_2d(lwline_in->points) / 1e14; pa1 = ptarray_substring(lwline_in->points, 0, loc, vstol); pa2 = ptarray_substring(lwline_in->points, loc, 1, vstol); /* NOTE: I've seen empty pointarrays with loc != 0 and loc != 1 */ if ( pa1->npoints == 0 || pa2->npoints == 0 ) { ptarray_free(pa1); ptarray_free(pa2); /* Intersection is on the boundary */ return 1; } lwmline_add_lwline(v, lwline_construct(SRID_UNKNOWN, NULL, pa1)); lwmline_add_lwline(v, lwline_construct(SRID_UNKNOWN, NULL, pa2)); return 2; }